package net.tropicraft.world.mapgen; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.util.ChunkCoordinates; import net.minecraft.world.World; import net.tropicraft.registry.TCBlockRegistry; import net.tropicraft.world.perlin.generator.RidgedMulti; public class MapGenUndergroundGrove { private static final int CHUNK_SIZE_Y = 256; private World worldObj; public boolean isActive = false; public int centerX = 0; public int centerZ = 0; public double length; public double width; public double height; public int y; public MapGenUndergroundGrove(World worldObj) { this.worldObj = worldObj; } public Block[] generate(int x, int z, Block[] blocks, byte[] metas) { ChunkCoordinates groveCoords = getGroveNear(worldObj, x, z); if(groveCoords != null) { centerX = groveCoords.posX; y = groveCoords.posY; centerZ = groveCoords.posZ; x *= 16; z *= 16; } else { return blocks; } isActive = true; Random rand = new Random(worldObj.getSeed() * centerX + centerZ * 57647382913L); RidgedMulti ridged = new RidgedMulti(rand.nextLong(), 1); ridged.frequency = 0.0325; length = rand.nextInt(20) + 30; width = rand.nextInt(20) + 30; height = rand.nextInt(3) + 5; length *= length; width *= width; height *= height; for(int i = 0; i < 16; i++) { for(int k = 0; k < 16; k++) { int relativeX = (x + i) - centerX; int relativeZ = (z + k) - centerZ; relativeX *= relativeX; relativeZ *= relativeZ; for(double j = -height; j < height; j++) { if((relativeX / length) + ((j * j) / height) + (relativeZ / width) <= 1) { placeBlock(i, y + (int)j, k, Blocks.air, blocks); } } double noise1 = ridged.getNoise(x + i, z + k); double noise2 = ridged.getNoise(x + i + 15432, z + k + 42314); if(noise1 > 0.845 || noise2 > 0.855) { int j = (int)Math.sqrt(height - ((height * relativeX) / length) - ((height * relativeZ) / width)); placeBlock(i, y - j - 1, k, Blocks.dirt, blocks); double tunnelHeight = (5 - (((relativeX / 2500D) + (relativeZ / 2500D)) * 2)) / 3; for(int j2 = 0; j2 < tunnelHeight; j2++) { placeBlock(i, y - j + j2, k, Blocks.air, blocks); } } if((i + x) % 16 == 0 && (k + z) % 16 == 0) { int j = (int)Math.sqrt(height - ((height * relativeX) / length) - ((height * relativeZ) / width)); rand.setSeed(i * k * 54325432 * worldObj.getSeed() * relativeX * centerX); if(getBlock(i, y - j, k, blocks) == Blocks.air && getBlock(i, y - j + 1, k, blocks) == Blocks.air && getBlock(i, y - j + 2, k, blocks) == Blocks.air && rand.nextInt(3) != 0) { placeBlockAndMeta(i, y - j, k, TCBlockRegistry.tikiTorch, 1, blocks, metas); placeBlockAndMeta(i, y - j + 1, k, TCBlockRegistry.tikiTorch, 1, blocks, metas); placeBlockAndMeta(i, y - j + 2, k, TCBlockRegistry.tikiTorch, 0, blocks, metas); } } } } return blocks; } public int getHeightAt(int x, int z) { int relativeX = x - centerX; int relativeZ = z - centerZ; relativeX *= relativeX; relativeZ *= relativeZ; return y - (int)Math.sqrt(height - ((height * relativeX) / length) - ((height * relativeZ) / width)); } /** * Method to choose spawn locations for volcanos (borrowed from village gen) * Rarity is determined by the numChunks/offsetChunks vars (smaller numbers * mean more spawning) */ protected boolean canGenGroveAtCoords(World worldObj, int i, int j) { byte numChunks = 32; byte offsetChunks = 8; int oldi = i; int oldj = j; if (i < 0) { i -= numChunks - 1; } if (j < 0) { j -= numChunks - 1; } int randX = i / numChunks; int randZ = j / numChunks; long seed = (long)randX * 341832132712L + (long)randZ * 422843987541L + worldObj.getWorldInfo().getSeed() + (long)42231726; Random rand = new Random(seed); randX *= numChunks; randZ *= numChunks; randX += rand.nextInt(numChunks - offsetChunks); randZ += rand.nextInt(numChunks - offsetChunks); if (oldi == randX && oldj == randZ) { return true; } return false; } /** * Returns the coordinates of a grove if it should be spawned near * this chunk, otherwise returns null. * The posY of the returned object should be used as the grove radius */ public ChunkCoordinates getGroveNear(World worldObj, int i, int j) { //Check 4 chunks in each direction (Groves are never more than 4 chunks wide) int range = 4; for(int x = i - range; x <= i + range; x++) { for(int z = j - range; z <= j + range; z++) { Random rand = new Random(worldObj.getSeed() * x + z * 57647382913L); if (canGenGroveAtCoords(worldObj, x, z)) { return new ChunkCoordinates(x * 16 + 8, rand.nextInt(5) + 20, z * 16 + 8); } } } return null; } private void placeBlock(int x, int y, int z, Block block, Block[] blocks) { blocks[x * CHUNK_SIZE_Y * 16 | z * CHUNK_SIZE_Y | y] = block; } private void placeBlockAndMeta(int x, int y, int z, Block block, int meta, Block[] blocks, byte[] metas) { blocks[x * CHUNK_SIZE_Y * 16 | z * CHUNK_SIZE_Y | y] = block; metas[x * CHUNK_SIZE_Y * 16 | z * CHUNK_SIZE_Y | y] = (byte)(meta & 0xF); } private Block getBlock(int x, int y, int z, Block[] blocks) { return blocks[x * CHUNK_SIZE_Y * 16 | z * CHUNK_SIZE_Y | y]; } }