package mcjty.rftools.dimension.world; import mcjty.rftools.blocks.dimlets.DimletConfiguration; import mcjty.rftools.dimension.DimensionInformation; import mcjty.rftools.dimension.RfToolsDimensionManager; import mcjty.rftools.dimension.description.MobDescriptor; import mcjty.rftools.dimension.world.mapgen.*; import mcjty.rftools.dimension.world.terrain.*; import mcjty.rftools.dimension.world.types.FeatureType; import mcjty.rftools.dimension.world.types.StructureType; import mcjty.rftools.dimension.world.types.TerrainType; import net.minecraft.block.Block; import net.minecraft.block.BlockFalling; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.passive.IAnimals; import net.minecraft.init.Blocks; import net.minecraft.util.IProgressUpdate; import net.minecraft.world.ChunkPosition; import net.minecraft.world.SpawnerAnimals; import net.minecraft.world.World; import net.minecraft.world.WorldType; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.MapGenBase; import net.minecraft.world.gen.MapGenCaves; import net.minecraft.world.gen.MapGenRavine; import net.minecraft.world.gen.feature.WorldGenDungeons; import net.minecraft.world.gen.feature.WorldGenLakes; import net.minecraft.world.gen.structure.*; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.terraingen.PopulateChunkEvent; import net.minecraftforge.event.terraingen.TerrainGen; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import static net.minecraftforge.event.terraingen.InitMapGenEvent.EventType.*; import static net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType.*; public class GenericChunkProvider implements IChunkProvider { public Random rand; public long seed; private World worldObj; public DimensionInformation dimensionInformation; private List<BiomeGenBase.SpawnListEntry> extraSpawns; private List<Integer> extraSpawnsMax; private final BaseTerrainGenerator terrainGenerator; // Are map structures going to be generated (e.g. strongholds) public WorldType worldType; private MapGenBase caveGenerator = new MapGenCaves(); // RFTools specific features. private MapGenTendrils tendrilGenerator = new MapGenTendrils(this); private MapGenCanyons canyonGenerator = new MapGenCanyons(this); private MapGenPyramids pyramidGenerator = new MapGenPyramids(this); private MapGenOrbs sphereGenerator = new MapGenOrbs(this, false); private MapGenOrbs hugeSphereGenerator = new MapGenOrbs(this, true); private MapGenRuinedCities ruinedCitiesGenerator = new MapGenRuinedCities(this); private MapGenLiquidOrbs liquidSphereGenerator = new MapGenLiquidOrbs(this, false); private MapGenLiquidOrbs hugeLiquidSphereGenerator = new MapGenLiquidOrbs(this, true); private MapGenBase denseCaveGenerator = new MapGenDenseCaves(this); // Holds Stronghold Generator private MapGenStronghold strongholdGenerator = new MapGenStronghold(); // Holds Village Generator private MapGenVillage villageGenerator = new MapGenVillage(); // Holds Mineshaft Generator private MapGenMineshaft mineshaftGenerator = new MapGenMineshaft(); // For nether fortresses public MapGenNetherBridge genNetherBridge = new MapGenNetherBridge(); private MapGenScatteredFeature scatteredFeatureGenerator = new MapGenScatteredFeature(); // Holds ravine generator private MapGenBase ravineGenerator = new MapGenRavine(); // The biomes that are used to generate the chunk public BiomeGenBase[] biomesForGeneration; { caveGenerator = TerrainGen.getModdedMapGen(caveGenerator, CAVE); // tendrilGenerator = TerrainGen.getModdedMapGen(tendrilGenerator, CAVE); // canyonGenerator = TerrainGen.getModdedMapGen(canyonGenerator, RAVINE); // sphereGenerator = TerrainGen.getModdedMapGen(sphereGenerator, RAVINE); strongholdGenerator = (MapGenStronghold) TerrainGen.getModdedMapGen(strongholdGenerator, STRONGHOLD); villageGenerator = (MapGenVillage) TerrainGen.getModdedMapGen(villageGenerator, VILLAGE); mineshaftGenerator = (MapGenMineshaft) TerrainGen.getModdedMapGen(mineshaftGenerator, MINESHAFT); scatteredFeatureGenerator = (MapGenScatteredFeature) TerrainGen.getModdedMapGen(scatteredFeatureGenerator, SCATTERED_FEATURE); ravineGenerator = TerrainGen.getModdedMapGen(ravineGenerator, RAVINE); genNetherBridge = (MapGenNetherBridge) TerrainGen.getModdedMapGen(genNetherBridge, NETHER_BRIDGE); } public GenericChunkProvider(World world, long seed) { this.worldObj = world; dimensionInformation = RfToolsDimensionManager.getDimensionManager(world).getDimensionInformation(world.provider.dimensionId); this.worldType = world.getWorldInfo().getTerrainType(); if (dimensionInformation.getTerrainType() == TerrainType.TERRAIN_AMPLIFIED) { worldType = WorldType.AMPLIFIED; } else if (dimensionInformation.getTerrainType() == TerrainType.TERRAIN_NORMAL && !DimletConfiguration.normalTerrainInheritsOverworld) { worldType = WorldType.DEFAULT; } else if (dimensionInformation.getTerrainType() == TerrainType.TERRAIN_FLAT) { worldType = WorldType.FLAT; } this.seed = seed; this.rand = new Random((seed + 516) * 314); switch (dimensionInformation.getTerrainType()) { case TERRAIN_VOID: terrainGenerator = new VoidTerrainGenerator(); break; case TERRAIN_FLAT: terrainGenerator = new FlatTerrainGenerator((byte) 63); break; case TERRAIN_AMPLIFIED: terrainGenerator = new AmplifiedTerrainGenerator(); break; case TERRAIN_NEARLANDS: terrainGenerator = new NearlandsTerrainGenerator(); break; case TERRAIN_NORMAL: terrainGenerator = new NormalTerrainGenerator(); break; case TERRAIN_CAVERN_OLD: terrainGenerator = new CavernTerrainGenerator(CavernTerrainGenerator.CavernHeight.HEIGHT_256); break; case TERRAIN_ISLAND: terrainGenerator = new IslandTerrainGenerator(IslandTerrainGenerator.NORMAL); break; case TERRAIN_ISLANDS: terrainGenerator = new IslandTerrainGenerator(IslandTerrainGenerator.ISLANDS); break; case TERRAIN_CHAOTIC: terrainGenerator = new IslandTerrainGenerator(IslandTerrainGenerator.CHAOTIC); break; case TERRAIN_PLATEAUS: terrainGenerator = new IslandTerrainGenerator(IslandTerrainGenerator.PLATEAUS); break; case TERRAIN_GRID: terrainGenerator = new GridTerrainGenerator(); break; case TERRAIN_CAVERN: terrainGenerator = new CavernTerrainGenerator(null); break; case TERRAIN_LOW_CAVERN: terrainGenerator = new CavernTerrainGenerator(CavernTerrainGenerator.CavernHeight.HEIGHT_128); break; case TERRAIN_FLOODED_CAVERN: terrainGenerator = new CavernTerrainGenerator(CavernTerrainGenerator.CavernHeight.HEIGHT_128); break; case TERRAIN_LIQUID: terrainGenerator = new LiquidTerrainGenerator(); break; case TERRAIN_SOLID: terrainGenerator = new FlatTerrainGenerator((byte) 127); break; case TERRAIN_WAVES: terrainGenerator = new WavesTerrainGenerator(false); break; case TERRAIN_FILLEDWAVES: terrainGenerator = new WavesTerrainGenerator(true); break; case TERRAIN_ROUGH: terrainGenerator = new RoughTerrainGenerator(false); break; default: terrainGenerator = new VoidTerrainGenerator(); break; } terrainGenerator.setup(world, this); extraSpawns = new ArrayList<BiomeGenBase.SpawnListEntry>(); extraSpawnsMax = new ArrayList<Integer>(); for (MobDescriptor mob : dimensionInformation.getExtraMobs()) { Class<? extends EntityLiving> entityClass = mob.getEntityClass(); extraSpawns.add(new BiomeGenBase.SpawnListEntry(entityClass, mob.getSpawnChance(), mob.getMinGroup(), mob.getMaxGroup())); extraSpawnsMax.add(mob.getMaxLoaded()); } } /** * loads or generates the chunk at the chunk location specified */ @Override public Chunk loadChunk(int chunkX, int chunkZ) { return this.provideChunk(chunkX, chunkZ); } /** * Will return back a chunk, if it doesn't exist and its not a MP client it will generates all the blocks for the * specified chunk from the map seed and chunk seed */ @Override public Chunk provideChunk(int chunkX, int chunkZ) { this.rand.setSeed(chunkX * 341873128712L + chunkZ * 132897987541L + 123456); Block[] ablock = new Block[65536]; byte[] abyte = new byte[65536]; this.biomesForGeneration = this.worldObj.getWorldChunkManager().getBiomesForGeneration(this.biomesForGeneration, chunkX * 4 - 2, chunkZ * 4 - 2, 10, 10); terrainGenerator.generate(chunkX, chunkZ, ablock, abyte); this.biomesForGeneration = this.worldObj.getWorldChunkManager().loadBlockGeneratorData(this.biomesForGeneration, chunkX * 16, chunkZ * 16, 16, 16); terrainGenerator.replaceBlocksForBiome(chunkX, chunkZ, ablock, abyte, this.biomesForGeneration); if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_TENDRILS)) { this.tendrilGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_CANYONS)) { this.canyonGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_PYRAMIDS)) { this.pyramidGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_ORBS)) { this.sphereGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_HUGEORBS)) { this.hugeSphereGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_LIQUIDORBS)) { this.liquidSphereGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_HUGELIQUIDORBS)) { this.hugeLiquidSphereGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_CAVES)) { this.caveGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_DENSE_CAVES)) { this.denseCaveGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_RAVINES)) { this.ravineGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_MINESHAFT)) { this.mineshaftGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_VILLAGE)) { this.villageGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_STRONGHOLD)) { this.strongholdGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_FORTRESS)) { this.genNetherBridge.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_SCATTERED)) { this.scatteredFeatureGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, ablock); } // this.ruinedCitiesGenerator.generate(this.worldObj, chunkX, chunkZ, ablock, abyte); Chunk chunk = new Chunk(this.worldObj, ablock, abyte, chunkX, chunkZ); byte[] abyte1 = chunk.getBiomeArray(); for (int k = 0; k < abyte1.length; ++k) { abyte1[k] = (byte) this.biomesForGeneration[k].biomeID; } chunk.generateSkylightMap(); return chunk; } /** * Checks to see if a chunk exists at x, y */ @Override public boolean chunkExists(int chunkX, int chunkZ) { return true; } /** * Populates chunk with ores etc etc */ @Override public void populate(IChunkProvider chunkProvider, int chunkX, int chunkZ) { BlockFalling.fallInstantly = true; int x = chunkX * 16; int z = chunkZ * 16; BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(x + 16, z + 16); this.rand.setSeed(this.worldObj.getSeed()); long i1 = this.rand.nextLong() / 2L * 2L + 1L; long j1 = this.rand.nextLong() / 2L * 2L + 1L; this.rand.setSeed(chunkX * i1 + chunkZ * j1 ^ this.worldObj.getSeed()); boolean flag = false; MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Pre(chunkProvider, worldObj, rand, chunkX, chunkZ, flag)); if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_MINESHAFT)) { this.mineshaftGenerator.generateStructuresInChunk(this.worldObj, this.rand, chunkX, chunkZ); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_VILLAGE)) { flag = this.villageGenerator.generateStructuresInChunk(this.worldObj, this.rand, chunkX, chunkZ); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_STRONGHOLD)) { this.strongholdGenerator.generateStructuresInChunk(this.worldObj, this.rand, chunkX, chunkZ); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_FORTRESS)) { this.genNetherBridge.generateStructuresInChunk(this.worldObj, this.rand, chunkX, chunkZ); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_SCATTERED)) { this.scatteredFeatureGenerator.generateStructuresInChunk(this.worldObj, this.rand, chunkX, chunkZ); } int k1; int l1; int i2; if (dimensionInformation.hasFeatureType(FeatureType.FEATURE_LAKES)) { if (dimensionInformation.getFluidsForLakes().length == 0) { // No specific liquid dimlets specified: we generate default lakes (water and lava were appropriate). if (biomegenbase != BiomeGenBase.desert && biomegenbase != BiomeGenBase.desertHills && !flag && this.rand.nextInt(4) == 0 && TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, LAKE)) { k1 = x + this.rand.nextInt(16) + 8; l1 = this.rand.nextInt(256); i2 = z + this.rand.nextInt(16) + 8; (new WorldGenLakes(Blocks.water)).generate(this.worldObj, this.rand, k1, l1, i2); } if (TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, LAVA) && !flag && this.rand.nextInt(8) == 0) { k1 = x + this.rand.nextInt(16) + 8; l1 = this.rand.nextInt(this.rand.nextInt(248) + 8); i2 = z + this.rand.nextInt(16) + 8; if (l1 < 63 || this.rand.nextInt(10) == 0) { (new WorldGenLakes(Blocks.lava)).generate(this.worldObj, this.rand, k1, l1, i2); } } } else { // Generate lakes for the specified biomes. for (Block liquid : dimensionInformation.getFluidsForLakes()) { if (!flag && this.rand.nextInt(4) == 0 && TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, LAKE)) { k1 = x + this.rand.nextInt(16) + 8; l1 = this.rand.nextInt(256); i2 = z + this.rand.nextInt(16) + 8; (new WorldGenLakes(liquid)).generate(this.worldObj, this.rand, k1, l1, i2); } } } } boolean doGen = false; if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_DUNGEON)) { doGen = TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, DUNGEON); for (k1 = 0; doGen && k1 < 8; ++k1) { l1 = x + this.rand.nextInt(16) + 8; i2 = this.rand.nextInt(256); int j2 = z + this.rand.nextInt(16) + 8; (new WorldGenDungeons()).generate(this.worldObj, this.rand, l1, i2, j2); } } biomegenbase.decorate(this.worldObj, this.rand, x, z); if (TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, ANIMALS)) { SpawnerAnimals.performWorldGenSpawning(this.worldObj, biomegenbase, x + 8, z + 8, 16, 16, this.rand); } x += 8; z += 8; doGen = TerrainGen.populate(chunkProvider, worldObj, rand, chunkX, chunkZ, flag, ICE); for (k1 = 0; doGen && k1 < 16; ++k1) { for (l1 = 0; l1 < 16; ++l1) { i2 = this.worldObj.getPrecipitationHeight(x + k1, z + l1); if (this.worldObj.isBlockFreezable(k1 + x, i2 - 1, l1 + z)) { this.worldObj.setBlock(k1 + x, i2 - 1, l1 + z, Blocks.ice, 0, 2); } if (this.worldObj.func_147478_e(k1 + x, i2, l1 + z, true)) { this.worldObj.setBlock(k1 + x, i2, l1 + z, Blocks.snow_layer, 0, 2); } } } MinecraftForge.EVENT_BUS.post(new PopulateChunkEvent.Post(chunkProvider, worldObj, rand, chunkX, chunkZ, flag)); BlockFalling.fallInstantly = false; } /** * Two modes of operation: if passed true, save all Chunks in one go. If passed false, save up to two chunks. * Return true if all chunks have been saved. */ @Override public boolean saveChunks(boolean p_73151_1_, IProgressUpdate progressUpdate) { return true; } /** * Save extra data not associated with any Chunk. Not saved during autosave, only during world unload. Currently * unimplemented. */ @Override public void saveExtraData() { } /** * Unloads chunks that are marked to be unloaded. This is not guaranteed to unload every such chunk. */ @Override public boolean unloadQueuedChunks() { return false; } /** * Returns if the IChunkProvider supports saving. */ @Override public boolean canSave() { return true; } /** * Converts the instance data to a readable string. */ @Override public String makeString() { return "RandomLevelSource"; } /** * Returns a list of creatures of the specified type that can spawn at the given location. */ @Override public List getPossibleCreatures(EnumCreatureType creatureType, int x, int y, int z) { List creatures = getDefaultCreatures(creatureType, x, y, z); if (extraSpawns.isEmpty()) { return creatures; } if (creatureType == EnumCreatureType.ambient) { creatures = new ArrayList(creatures); for (int i = 0 ; i < extraSpawns.size() ; i++) { Class entityClass = extraSpawns.get(i).entityClass; if (IAnimals.class.isAssignableFrom(entityClass)) { int count = worldObj.countEntities(entityClass); if (count < extraSpawnsMax.get(i)) { creatures.add(extraSpawns.get(i)); } } } } else if (creatureType == EnumCreatureType.monster) { creatures = new ArrayList(creatures); for (int i = 0 ; i < extraSpawns.size() ; i++) { Class entityClass = extraSpawns.get(i).entityClass; if (IMob.class.isAssignableFrom(entityClass)) { int count = worldObj.countEntities(entityClass); if (count < extraSpawnsMax.get(i)) { creatures.add(extraSpawns.get(i)); } } } } return creatures; } private List getDefaultCreatures(EnumCreatureType creatureType, int x, int y, int z) { BiomeGenBase biomegenbase = this.worldObj.getBiomeGenForCoords(x, z); if (creatureType == EnumCreatureType.monster) { if (dimensionInformation.isPeaceful()) { return Collections.emptyList(); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_SCATTERED)) { if (this.scatteredFeatureGenerator.func_143030_a(x, y, z)) { return this.scatteredFeatureGenerator.getScatteredFeatureSpawnList(); } } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_FORTRESS)) { if (this.genNetherBridge.hasStructureAt(x, y, z)) { return this.genNetherBridge.getSpawnList(); } if (this.genNetherBridge.func_142038_b(x, y, z) && this.worldObj.getBlock(x, y - 1, z) == Blocks.nether_brick) { return this.genNetherBridge.getSpawnList(); } } } else if (creatureType == EnumCreatureType.ambient) { if (dimensionInformation.isNoanimals()) { return Collections.emptyList(); } } return biomegenbase.getSpawnableList(creatureType); } @Override public ChunkPosition func_147416_a(World world, String name, int x, int y, int z) { return "Stronghold".equals(name) && this.strongholdGenerator != null ? this.strongholdGenerator.func_151545_a(world, x, y, z) : null; } @Override public int getLoadedChunkCount() { return 0; } @Override public void recreateStructures(int chunkX, int chunkZ) { if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_MINESHAFT)) { this.mineshaftGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, null); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_VILLAGE)) { this.villageGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, null); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_STRONGHOLD)) { this.strongholdGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, null); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_FORTRESS)) { this.genNetherBridge.func_151539_a(this, this.worldObj, chunkX, chunkZ, null); } if (dimensionInformation.hasStructureType(StructureType.STRUCTURE_SCATTERED)) { this.scatteredFeatureGenerator.func_151539_a(this, this.worldObj, chunkX, chunkZ, null); } } }