package erebus.world.structure; import java.util.Random; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraft.world.chunk.ChunkPrimer; import net.minecraft.world.gen.MapGenBase; import erebus.ModBlocks; public class MapGenErebusCaves extends MapGenBase { protected static final IBlockState BLOCK_AIR = Blocks.AIR.getDefaultState(); protected void generateLargeCaveNode(long seed, int chunkX, int chunkZ, ChunkPrimer primer, double xx, double yy, double zz) { generateCaveNode(seed, chunkX, chunkZ, primer, xx, yy, zz, 1F + rand.nextFloat() * 3F, 0F, 0F, -1, -1, rand.nextDouble() * 0.5D + 0.3D); } @Override public void generate(World worldIn, int x, int z, ChunkPrimer primer) { int i = this.range; this.worldObj = worldIn; this.rand.setSeed(worldIn.getSeed()); long j = this.rand.nextLong(); long k = this.rand.nextLong(); for (int l = x - i; l <= x + i; ++l) { for (int i1 = z - i; i1 <= z + i; ++i1) { long j1 = (long)l * j; long k1 = (long)i1 * k; this.rand.setSeed(j1 ^ k1 ^ worldIn.getSeed()); this.recursiveGenerate(worldIn, l, i1, x, z, primer); } } } protected void generateCaveNode(long seed, int chunkX, int chunkZ, ChunkPrimer primer, double xx, double yy, double zz, float innerSize, float xzAngle, float yAngle, int par15, int par16, double heightMp) { double centerX = chunkX * 16 + 8; double centerZ = chunkZ * 16 + 8; float f3 = 0F; float f4 = 0F; Random rand = new Random(seed); if (par16 <= 0) { int j1 = range * 16 - 16; par16 = j1 - rand.nextInt(j1 / 4); } boolean flag = false; if (par15 == -1) { par15 = par16 / 2; flag = true; } int k1 = rand.nextInt(par16 / 2) + par16 / 4; for (boolean steep = rand.nextInt(6) == 0; par15 < par16; ++par15) { double xzRange = 1.5D + MathHelper.sin(par15 * (float) Math.PI / par16) * innerSize * 1F; double yRange = xzRange * heightMp; float f5 = MathHelper.cos(yAngle); float f6 = MathHelper.sin(yAngle); xx += MathHelper.cos(xzAngle) * f5; yy += f6; zz += MathHelper.sin(xzAngle) * f5; if (steep) yAngle *= 0.92F; else yAngle *= 0.7F; yAngle += f4 * 0.1F; xzAngle += f3 * 0.1F; f4 *= 0.9F; f3 *= 0.75F; f4 += (rand.nextFloat() - rand.nextFloat()) * rand.nextFloat() * 2F; f3 += (rand.nextFloat() - rand.nextFloat()) * rand.nextFloat() * 4F; if (!flag && par15 == k1 && innerSize > 1F) { generateCaveNode(rand.nextLong(), chunkX, chunkZ, primer, xx, yy, zz, rand.nextFloat() * 0.5F + 0.5F, xzAngle - (float) Math.PI / 2F, yAngle / 3F, par15, par16, 1D); generateCaveNode(rand.nextLong(), chunkX, chunkZ, primer, xx, yy, zz, rand.nextFloat() * 0.5F + 0.5F, xzAngle + (float) Math.PI / 2F, yAngle / 3F, par15, par16, 1D); return; } if (flag || rand.nextInt(4) != 0) { double diffX = xx - centerX; double diffZ = zz - centerZ; double d10 = par16 - par15; double radius = innerSize + 2F + 16F; if (diffX * diffX + diffZ * diffZ - d10 * d10 > radius * radius) return; if (xx >= centerX - 16D - xzRange * 2D && zz >= centerZ - 16D - xzRange * 2D && xx <= centerX + 16D + xzRange * 2D && zz <= centerZ + 16D + xzRange * 2D) { int minX = MathHelper.floor_double(xx - xzRange) - chunkX * 16 - 1; int maxX = MathHelper.floor_double(xx + xzRange) - chunkX * 16 + 1; int minY = MathHelper.floor_double(yy - yRange) - 1; int maxY = MathHelper.floor_double(yy + yRange) + 1; int minZ = MathHelper.floor_double(zz - xzRange) - chunkZ * 16 - 1; int maxZ = MathHelper.floor_double(zz + xzRange) - chunkZ * 16 + 1; if (minX < 0) minX = 0; if (maxX > 16) maxX = 16; if (minY < 6) minY = 6; if (maxY > 124) maxY = 124; if (minZ < 0) minZ = 0; if (maxZ > 16) maxZ = 16; boolean preventGeneration = false; for (int px = minX; !preventGeneration && px < maxX; ++px) for (int pz = minZ; !preventGeneration && pz < maxZ; ++pz) for (int py = maxY + 1; !preventGeneration && py >= minY - 1; --py) if (py >= 0 && py < 128) if (py != minY - 1 && px != minX && px != maxX - 1 && pz != minZ && pz != maxZ - 1) py = minY; if (!preventGeneration) { for (int px = minX; px < maxX; ++px) { double xDiff = (px + chunkX * 16 + 0.5D - xx) / xzRange; for (int pz = minZ; pz < maxZ; ++pz) { double zDiff = (pz + chunkZ * 16 + 0.5D - zz) / xzRange; if (xDiff * xDiff + zDiff * zDiff < 1D) for (int py = maxY - 1; py >= minY; --py) { double yDiff = (py + 0.5D - yy) / yRange; if (yDiff > -0.7D && xDiff * xDiff + yDiff * yDiff + zDiff * zDiff < 1D) { IBlockState state = primer.getBlockState(px, py, pz); if (state.getBlock() == ModBlocks.UMBERSTONE || state.getBlock() == Blocks.DIRT || state.getBlock() == Blocks.GRASS) primer.setBlockState(px, py, pz, BLOCK_AIR); } } } } if (flag) break; } } } } } @Override protected void recursiveGenerate(World worldIn, int chunkX, int chunkZ, int localX, int localZ, ChunkPrimer primer) { int caveAmount = rand.nextInt(rand.nextInt(25) + 1); if (rand.nextInt(10) != 0) caveAmount = 0; for (int iter = 0; iter < caveAmount; ++iter) { double xx = localX * 16 + rand.nextInt(16); double yy = 68 + rand.nextGaussian() * 48D; double zz = localZ * 16 + rand.nextInt(16); int smallCaves = rand.nextBoolean() && rand.nextBoolean() ? 2 : 1; if (rand.nextInt(8) == 0) { generateLargeCaveNode(rand.nextLong(), chunkX, chunkZ, primer, xx, yy, zz); smallCaves += rand.nextInt(3); } for (int cave = 0; cave < smallCaves; ++cave) { float xzAngle = rand.nextFloat() * (float) Math.PI * 2F; float yAngle = (rand.nextFloat() - 0.5F) * 2F / 8F; float innerSize = rand.nextFloat() * 2.5F + rand.nextFloat(); if (rand.nextInt(10) == 0) innerSize *= rand.nextFloat() * rand.nextFloat() + 1F; generateCaveNode(rand.nextLong(), chunkX, chunkZ, primer, xx, yy, zz, innerSize, xzAngle, yAngle, 0, 0, 1D); } } } }