package mcjty.rftools.dimension.world.terrain; import cpw.mods.fml.common.eventhandler.Event; import mcjty.rftools.dimension.world.GenericChunkProvider; import mcjty.rftools.dimension.world.types.FeatureType; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.init.Blocks; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.gen.NoiseGenerator; import net.minecraft.world.gen.NoiseGeneratorOctaves; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.terraingen.ChunkProviderEvent; import net.minecraftforge.event.terraingen.TerrainGen; import java.util.Random; public class IslandTerrainGenerator implements BaseTerrainGenerator { private GenericChunkProvider provider; private double[] densities; private NoiseGeneratorOctaves noiseGen1; private NoiseGeneratorOctaves noiseGen2; private NoiseGeneratorOctaves noiseGen3; private NoiseGeneratorOctaves noiseGen4; private NoiseGeneratorOctaves noiseGen5; private double[] stoneNoise = new double[256]; private double[] noiseData1; private double[] noiseData2; private double[] noiseData3; private double[] noiseData4; private double[] noiseData5; public static final int NORMAL = 0; public static final int CHAOTIC = 1; public static final int PLATEAUS = 3; public static final int ISLANDS = 4; private final int type; private final double topFactor; private final double botFactor; private final int bottomOffset; public IslandTerrainGenerator(int type) { this.type = type; switch (type) { case PLATEAUS: topFactor = -1000.0D; botFactor = -300.0D; break; case ISLANDS: topFactor = -600.0D; botFactor = -200.0D; break; default: topFactor = -3000.0D; botFactor = -30.D; break; } if (type == PLATEAUS) { bottomOffset = 14; } else if (type == ISLANDS) { bottomOffset = 11; } else { bottomOffset = 8; } } @Override public void setup(World world, GenericChunkProvider provider) { this.provider = provider; this.noiseGen1 = new NoiseGeneratorOctaves(provider.rand, 16); this.noiseGen2 = new NoiseGeneratorOctaves(provider.rand, 16); this.noiseGen3 = new NoiseGeneratorOctaves(provider.rand, 8); this.noiseGen4 = new NoiseGeneratorOctaves(provider.rand, 10); this.noiseGen5 = new NoiseGeneratorOctaves(provider.rand, 16); NoiseGenerator[] noiseGens = {noiseGen1, noiseGen2, noiseGen3, noiseGen4, noiseGen5}; noiseGens = TerrainGen.getModdedNoiseGenerators(world, provider.rand, noiseGens); this.noiseGen1 = (NoiseGeneratorOctaves)noiseGens[0]; this.noiseGen2 = (NoiseGeneratorOctaves)noiseGens[1]; this.noiseGen3 = (NoiseGeneratorOctaves)noiseGens[2]; this.noiseGen4 = (NoiseGeneratorOctaves)noiseGens[3]; this.noiseGen5 = (NoiseGeneratorOctaves)noiseGens[4]; } /** * generates a subset of the level's terrain data. Takes 7 arguments: the [empty] noise array, the position, and the * size. */ private double[] initializeNoiseField(double[] densities, int chunkX2, int chunkY2, int chunkZ2, int sizeX, int sizeY, int sizeZ) { ChunkProviderEvent.InitNoiseField event = new ChunkProviderEvent.InitNoiseField(provider, densities, chunkX2, chunkY2, chunkZ2, sizeX, sizeY, sizeZ); MinecraftForge.EVENT_BUS.post(event); if (event.getResult() == Event.Result.DENY) { return event.noisefield; } if (densities == null) { densities = new double[sizeX * sizeY * sizeZ]; } boolean shallowOcean = provider.dimensionInformation.hasFeatureType(FeatureType.FEATURE_SHALLOW_OCEAN); double d0 = 684.412D; double d1 = 684.412D; this.noiseData4 = this.noiseGen4.generateNoiseOctaves(this.noiseData4, chunkX2, chunkZ2, sizeX, sizeZ, 1.121D, 1.121D, 0.5D); this.noiseData5 = this.noiseGen5.generateNoiseOctaves(this.noiseData5, chunkX2, chunkZ2, sizeX, sizeZ, 200.0D, 200.0D, 0.5D); d0 *= 2.0D; this.noiseData1 = this.noiseGen3.generateNoiseOctaves(this.noiseData1, chunkX2, chunkY2, chunkZ2, sizeX, sizeY, sizeZ, d0 / 80.0D, d1 / 160.0D, d0 / 80.0D); this.noiseData2 = this.noiseGen1.generateNoiseOctaves(this.noiseData2, chunkX2, chunkY2, chunkZ2, sizeX, sizeY, sizeZ, d0, d1, d0); this.noiseData3 = this.noiseGen2.generateNoiseOctaves(this.noiseData3, chunkX2, chunkY2, chunkZ2, sizeX, sizeY, sizeZ, d0, d1, d0); int k1 = 0; Random random = new Random(chunkX2 * 13 + chunkY2 * 157 + chunkZ2 * 13883); random.nextFloat(); for (int x = 0; x < sizeX; ++x) { for (int z = 0; z < sizeZ; ++z) { float f2 = 0.0f; switch (type) { case NORMAL: { float xx = (x + chunkX2) / 1.0F; float zz = (z + chunkZ2) / 1.0F; f2 = 100.0F - MathHelper.sqrt_float(xx * xx + zz * zz) * 8.0F; if (f2 > 80.0F) { f2 = 80.0F; } else if (f2 < -100.0F) { f2 = -100.0F; } break; } case CHAOTIC: f2 = 0.0F; break; case PLATEAUS: f2 = -5.0f; break; case ISLANDS: f2 = -20.0f; break; } for (int y = 0; y < sizeY; ++y) { double d5 = 0.0D; double d7 = this.noiseData2[k1] / 512.0D; double d8 = this.noiseData3[k1] / 512.0D; double d9 = (this.noiseData1[k1] / 10.0D + 1.0D) / 2.0D; if (d9 < 0.0D) { d5 = d7; } else if (d9 > 1.0D) { d5 = d8; } else { d5 = d7 + (d8 - d7) * d9; } d5 -= 8.0D; d5 += f2; int b0 = 2; double d10; if (y > ((sizeY / 2) - b0)) { d10 = ((y - (sizeY / 2 - b0)) / 64.0F); if (d10 < 0.0D) { d10 = 0.0D; } else if (d10 > 1.0D) { d10 = 1.0D; } d5 = d5 * (1.0D - d10) + topFactor * d10; } b0 = bottomOffset; if (y < b0) { d10 = ((b0 - y) / (b0 - 1.0F)); d5 = d5 * (1.0D - d10) + botFactor * d10; } if (shallowOcean && y == 0) { densities[k1] = 100.0f; } else if (shallowOcean && y == 1) { densities[k1] = 50.0f + (random.nextFloat() * 200.0f); } else { densities[k1] = d5; } ++k1; } } } return densities; } @Override public void generate(int chunkX, int chunkZ, Block[] aBlock, byte[] meta) { Block baseBlock = provider.dimensionInformation.getBaseBlockForTerrain().getBlock(); byte baseMeta = provider.dimensionInformation.getBaseBlockForTerrain().getMeta(); byte b0 = 2; int k = b0 + 1; byte b1 = 33; int l = b0 + 1; this.densities = this.initializeNoiseField(this.densities, chunkX * b0, 0, chunkZ * b0, k, b1, l); for (int x2 = 0; x2 < b0; ++x2) { for (int z2 = 0; z2 < b0; ++z2) { for (int height32 = 0; height32 < 32; ++height32) { double d0 = 0.25D; double d1 = this.densities[((x2 + 0) * l + z2 + 0) * b1 + height32 + 0]; double d2 = this.densities[((x2 + 0) * l + z2 + 1) * b1 + height32 + 0]; double d3 = this.densities[((x2 + 1) * l + z2 + 0) * b1 + height32 + 0]; double d4 = this.densities[((x2 + 1) * l + z2 + 1) * b1 + height32 + 0]; double d5 = (this.densities[((x2 + 0) * l + z2 + 0) * b1 + height32 + 1] - d1) * d0; double d6 = (this.densities[((x2 + 0) * l + z2 + 1) * b1 + height32 + 1] - d2) * d0; double d7 = (this.densities[((x2 + 1) * l + z2 + 0) * b1 + height32 + 1] - d3) * d0; double d8 = (this.densities[((x2 + 1) * l + z2 + 1) * b1 + height32 + 1] - d4) * d0; for (int h = 0; h < 8; ++h) { double d9 = 0.125D; double d10 = d1; double d11 = d2; double d12 = (d3 - d1) * d9; double d13 = (d4 - d2) * d9; int height = (height32 * 4) + h; for (int x = 0; x < 8; ++x) { int index = ((x + (x2 * 8)) << 12) | ((0 + (z2 * 8)) << 8) | height; short maxheight = 256; double d14 = 0.125D; double d15 = d10; double d16 = (d11 - d10) * d14; for (int z = 0; z < 8; ++z) { if (d15 > 0.0D) { aBlock[index] = baseBlock; byte realMeta; if (baseMeta == 127) { realMeta = (byte)((height/2 + x/2 + z/2) & 0xf); } else { realMeta = baseMeta; } meta[index] = realMeta; } else { aBlock[index] = null; } index += maxheight; d15 += d16; } d10 += d12; d11 += d13; } d1 += d5; d2 += d6; d3 += d7; d4 += d8; } } } } } @Override public void replaceBlocksForBiome(int chunkX, int chunkZ, Block[] aBlock, byte[] abyte, BiomeGenBase[] biomeGenBases) { // ChunkProviderEvent.ReplaceBiomeBlocks event = new ChunkProviderEvent.ReplaceBiomeBlocks(provider, chunkX, chunkZ, aBlock, abyte, biomeGenBases, world); // MinecraftForge.EVENT_BUS.post(event); // if (event.getResult() == Event.Result.DENY) { // return; // } double d0 = 0.03125D; this.stoneNoise = this.noiseGen4.generateNoiseOctaves(this.stoneNoise, (chunkX * 16), (chunkZ * 16), 16, 16, d0 * 2.0D, d0 * 2.0D, 1.0D); for (int k = 0; k < 16; ++k) { for (int l = 0; l < 16; ++l) { BiomeGenBase biomegenbase = biomeGenBases[l + k * 16]; genBiomeTerrain(biomegenbase, aBlock, abyte, chunkX * 16 + k, chunkZ * 16 + l, this.stoneNoise[l + k * 16]); } } } public final void genBiomeTerrain(BiomeGenBase biomegenbase, Block[] blocks, byte[] abyte, int x, int z, double noise) { Block baseLiquid = provider.dimensionInformation.getFluidForTerrain(); Block baseBlock = provider.dimensionInformation.getBaseBlockForTerrain().getBlock(); byte baseMeta = provider.dimensionInformation.getBaseBlockForTerrain().getMeta(); Block block = biomegenbase.topBlock; byte blockMeta = (byte)(biomegenbase.field_150604_aj & 255); Block block1 = biomegenbase.fillerBlock; //baseBlock byte block1Meta = (byte)(biomegenbase.field_76754_C & 255); int k = -1; int l = (int)(noise / 3.0D + 3.0D + provider.rand.nextDouble() * 0.25D); int cx = x & 15; int cz = z & 15; // Index of the bottom of the column. int bottomIndex = ((cz * 16) + cx) * (blocks.length / 256); boolean shallowOcean = provider.dimensionInformation.hasFeatureType(FeatureType.FEATURE_SHALLOW_OCEAN); int shallowWaterY = 30; for (int height = 255; height >= 0; --height) { int index = bottomIndex + height; if (height <= 2) { if (shallowOcean) { blocks[index] = Blocks.bedrock; } else { blocks[index] = Blocks.air; } } else { Block currentBlock = blocks[index]; if (currentBlock == Blocks.bedrock && height <= 12) { if (shallowOcean) { blocks[index] = baseLiquid; } else { blocks[index] = Blocks.air; } k = -1; } else { if (currentBlock != null && currentBlock.getMaterial() != Material.air) { if (currentBlock == baseBlock) { if (k == -1) { if (l <= 0) { block = null; blockMeta = 0; block1 = baseBlock; block1Meta = baseMeta; } else if (height >= 59 && height <= 64) { block = biomegenbase.topBlock; blockMeta = (byte) (biomegenbase.field_150604_aj & 255); block1 = baseBlock; //biomegenbase.fillerBlock; block1Meta = baseMeta; } if (height < 63 && (block == null || block.getMaterial() == Material.air)) { if (biomegenbase.getFloatTemperature(x, height, z) < 0.15F) { block = Blocks.ice; blockMeta = 0; } else { block = baseLiquid; blockMeta = 0; } } k = l; if (height >= 62) { blocks[index] = block; abyte[index] = blockMeta; } else if (height < 56 - l) { block = null; block1 = baseBlock; //Blocks.stone; block1Meta = baseMeta; blocks[index] = biomegenbase.fillerBlock;//Blocks.gravel; abyte[index] = (byte) (biomegenbase.field_76754_C & 266); } else { blocks[index] = block1; abyte[index] = block1Meta; } } else if (k > 0) { --k; blocks[index] = block1; abyte[index] = block1Meta; if (k == 0 && block1 == Blocks.sand) { k = provider.rand.nextInt(4) + Math.max(0, height - 63); block1 = Blocks.sandstone; block1Meta = 0; } } } } else { if (shallowOcean && height <= shallowWaterY) { blocks[index] = baseLiquid; } k = -1; } } } } } }