From b90c04c248f72710f1c865acc85ae6c6fea1bcb6 Mon Sep 17 00:00:00 2001 From: Bartosz Skrzypczak Date: Wed, 19 Oct 2016 18:51:07 +0200 Subject: [PATCH] Fixed recursive/reentrant chunk generation caused by lush caves, closes #275 (#294) --- .../actuallyadditions/mod/gen/OreGen.java | 24 +++++++++--- .../mod/gen/WorldGenLushCaves.java | 38 ++++++++++++++----- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/gen/OreGen.java b/src/main/java/de/ellpeck/actuallyadditions/mod/gen/OreGen.java index bce8aa58c..ac29f1440 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/gen/OreGen.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/gen/OreGen.java @@ -30,6 +30,7 @@ import net.minecraft.world.biome.BiomeOcean; import net.minecraft.world.chunk.IChunkGenerator; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.feature.WorldGenMinable; +import net.minecraft.world.gen.structure.StructureBoundingBox; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.terraingen.DecorateBiomeEvent; import net.minecraftforge.fml.common.IWorldGenerator; @@ -59,19 +60,32 @@ public class OreGen implements IWorldGenerator{ int dimension = world.provider.getDimension(); if(dimension != -1 && dimension != 1){ if(world.getWorldType() != WorldType.FLAT && !ArrayUtils.contains(ConfigIntListValues.ORE_GEN_DIMENSION_BLACKLIST.getValue(), world.provider.getDimension())){ - this.generateDefault(world, random, chunkX*16, chunkZ*16); + this.generateDefault(world, random, chunkX, chunkZ); } } } private void generateDefault(World world, Random random, int x, int z){ if(ConfigBoolValues.GENERATE_QUARTZ.isEnabled()){ - this.addOreSpawn(InitBlocks.blockMisc, TheMiscBlocks.ORE_QUARTZ.ordinal(), Blocks.STONE, world, random, x, z, MathHelper.getRandomIntegerInRange(random, 5, 8), 10, QUARTZ_MIN, QUARTZ_MAX); + this.addOreSpawn(InitBlocks.blockMisc, TheMiscBlocks.ORE_QUARTZ.ordinal(), Blocks.STONE, world, random, x*16, z*16, MathHelper.getRandomIntegerInRange(random, 5, 8), 10, QUARTZ_MIN, QUARTZ_MAX); } - if(ConfigBoolValues.GEN_LUSH_CAVES.isEnabled() && random.nextInt(ConfigIntValues.LUSH_CAVE_CHANCE.getValue()) <= 0){ - BlockPos posAtHeight = world.getTopSolidOrLiquidBlock(new BlockPos(x+random.nextInt(16)+8, 0, z+random.nextInt(16)+8)); - this.caveGen.generate(world, random, posAtHeight.down(MathHelper.getRandomIntegerInRange(random, 15, posAtHeight.getY()-15))); + if(ConfigBoolValues.GEN_LUSH_CAVES.isEnabled()){ + StructureBoundingBox box = new StructureBoundingBox(x*16+8, 0, z*16+8, x*16+8+15, 255, z*16+8+15); + int chunkRadius = 1; + for(int dx = -chunkRadius; dx <= chunkRadius; dx++) { + for(int dz = -chunkRadius; dz <= chunkRadius; dz++) { + int chunkX = x+dx; + int chunkZ = z+dz; + int randConst = 0x969ce69d;//so that it won't generate the same numbers as other mod that does the same thing + Random chunkRand = new Random(randConst ^ world.getSeed() ^ (chunkX*29+chunkZ*31)); + if(chunkRand.nextInt(ConfigIntValues.LUSH_CAVE_CHANCE.getValue()) <= 0) { + BlockPos randPos = new BlockPos(chunkX*16+chunkRand.nextInt(16)+8, 64, chunkZ*16+chunkRand.nextInt(16)+8); + BlockPos pos = randPos.down(MathHelper.getRandomIntegerInRange(chunkRand, 15, randPos.getY()-15)); + this.caveGen.generate(world, chunkRand, pos, box); + } + } + } } } diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/gen/WorldGenLushCaves.java b/src/main/java/de/ellpeck/actuallyadditions/mod/gen/WorldGenLushCaves.java index b44652792..67151bcd0 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/gen/WorldGenLushCaves.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/gen/WorldGenLushCaves.java @@ -17,6 +17,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.gen.feature.*; +import net.minecraft.world.gen.structure.StructureBoundingBox; import net.minecraft.world.storage.loot.ILootContainer; import java.util.ArrayList; @@ -24,30 +25,39 @@ import java.util.Collections; import java.util.List; import java.util.Random; -public class WorldGenLushCaves extends WorldGenerator{ +public class WorldGenLushCaves{ - @Override - public boolean generate(World world, Random rand, BlockPos position){ - this.generateCave(world, position, rand); + public boolean generate(World world, Random rand, BlockPos position, StructureBoundingBox blockRegion){ + this.generateCave(world, position, rand, blockRegion); return true; } - private void generateCave(World world, BlockPos center, Random rand){ + private void generateCave(World world, BlockPos center, Random rand, StructureBoundingBox chunkRegion){ int spheres = rand.nextInt(5)+3; + StructureBoundingBox spheresBox = new StructureBoundingBox(chunkRegion); + //the region for spheres is larger so that trees can generate in the smaller one + spheresBox.minX -= 7; + spheresBox.minZ -= 7; + spheresBox.maxX += 7; + spheresBox.maxZ += 7; for(int i = 0; i <= spheres; i++){ - this.makeSphereWithGrassFloor(world, center.add(rand.nextInt(11)-5, rand.nextInt(7)-3, rand.nextInt(11)-5), rand.nextInt(3)+5); + //center already is random value within population area + this.makeSphereWithGrassFloor(world, center.add(rand.nextInt(11)-5, rand.nextInt(7)-3, rand.nextInt(11)-5), rand.nextInt(3)+5, spheresBox); } - this.genTreesAndTallGrass(world, center, 10, spheres*3, rand); + this.genTreesAndTallGrass(world, center, 11, spheres*3, rand, chunkRegion); } - private void genTreesAndTallGrass(World world, BlockPos center, int radius, int amount, Random rand){ + private void genTreesAndTallGrass(World world, BlockPos center, int radius, int amount, Random rand, StructureBoundingBox box){ List possiblePoses = new ArrayList(); for(double x = -radius; x < radius; x++){ for(double y = -radius; y < radius; y++){ for(double z = -radius; z < radius; z++){ if(rand.nextDouble() >= 0.5D){ BlockPos pos = center.add(x, y, z); + if(!box.isVecInside(pos)) { + continue; + } if(world.getBlockState(pos).getBlock() == Blocks.GRASS){ possiblePoses.add(pos); } @@ -71,13 +81,14 @@ public class WorldGenLushCaves extends WorldGenerator{ } } - private void makeSphereWithGrassFloor(World world, BlockPos center, int radius){ + private void makeSphereWithGrassFloor(World world, BlockPos center, int radius, StructureBoundingBox boundingBox){ for(double x = -radius; x < radius; x++){ for(double y = -radius; y < radius; y++){ for(double z = -radius; z < radius; z++){ if(Math.sqrt((x*x)+(y*y)+(z*z)) < radius){ BlockPos pos = center.add(x, y, z); - if(!this.checkIndestructable(world, pos)){ + //Note: order matters, checkIndestructable will generate chunks if order is reversed + if(boundingBox.isVecInside(pos) && !this.checkIndestructable(world, pos)){ world.setBlockToAir(pos); } } @@ -89,6 +100,9 @@ public class WorldGenLushCaves extends WorldGenerator{ for(double z = -radius; z < radius; z++){ for(double y = -radius; y <= -3; y++){ BlockPos pos = center.add(x, y, z); + if(!boundingBox.isVecInside(pos)) { + continue; + } IBlockState state = world.getBlockState(pos); BlockPos posUp = pos.up(); IBlockState stateUp = world.getBlockState(posUp); @@ -112,6 +126,10 @@ public class WorldGenLushCaves extends WorldGenerator{ IBlockState state = world.getBlockState(pos); if(state != null){ Block block = state.getBlock(); + //check if it's tree or grass that is generated here + if(block == Blocks.LOG || block == Blocks.LEAVES || block == Blocks.TALLGRASS) { + return true; + } if(block != null && (block.isAir(state, world, pos) || block.getHarvestLevel(state) >= 0F)){ return false; }