Eliminate ALL cascading worldgen lag, with the following changes:

- Offset structures by minus half their width in x/z (as well as the usual +8), so they can't ever spill out of the 2x2 chunk area being generated (provided they are less than 16 blocks wide, which mine are)
- Pass the block placement flags 16 | 2 to Template#addBlocksToWorld instead of just 2, to prevent neighbour updates
- Ignore unloaded blocks when removing floating trees (in theory there can't be trees there anyway)
This commit is contained in:
Electroblob77
2020-07-13 21:38:37 +01:00
parent ded4caca2f
commit 2e3df272ec
8 changed files with 20 additions and 14 deletions
@@ -15,8 +15,6 @@ import java.util.Random;
public class WorldGenCrystalOre implements IWorldGenerator { public class WorldGenCrystalOre implements IWorldGenerator {
// TODO: Probably this and the flowers are causing cascading lag!
@Override @Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){ public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider){
@@ -41,7 +41,8 @@ public class WorldGenLibraryRuins extends WorldGenSurfaceStructure {
@Override @Override
public boolean canGenerate(Random random, World world, int chunkX, int chunkZ){ public boolean canGenerate(Random random, World world, int chunkX, int chunkZ){
return ArrayUtils.contains(Wizardry.settings.libraryDimensions, world.provider.getDimension()) return ArrayUtils.contains(Wizardry.settings.libraryDimensions, world.provider.getDimension())
&& BiomeDictionary.getTypes(world.getBiome(new BlockPos(chunkX * 16 + 8, 0, chunkZ * 16 + 8))) // +8 for the anti-cascading offset, and +8 for the middle of the generated area makes +16 in total
&& BiomeDictionary.getTypes(world.getBiome(new BlockPos(chunkX * 16 + 16, 0, chunkZ * 16 + 16)))
.stream().anyMatch(BIOME_TYPES::contains) .stream().anyMatch(BIOME_TYPES::contains)
&& Wizardry.settings.libraryRarity > 0 && random.nextInt(Wizardry.settings.libraryRarity) == 0; && Wizardry.settings.libraryRarity > 0 && random.nextInt(Wizardry.settings.libraryRarity) == 0;
} }
@@ -91,7 +92,7 @@ public class WorldGenLibraryRuins extends WorldGenSurfaceStructure {
} }
); );
template.addBlocksToWorld(world, origin, processor, settings, 2); template.addBlocksToWorld(world, origin, processor, settings, 2 | 16);
WizardryAntiqueAtlasIntegration.markLibrary(world, origin.getX(), origin.getZ()); WizardryAntiqueAtlasIntegration.markLibrary(world, origin.getX(), origin.getZ());
} }
@@ -62,7 +62,7 @@ public class WorldGenObelisk extends WorldGenSurfaceStructure {
ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo( ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo(
i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i; i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i;
template.addBlocksToWorld(world, origin, processor, settings, 2); template.addBlocksToWorld(world, origin, processor, settings, 2 | 16);
WizardryAntiqueAtlasIntegration.markObelisk(world, origin.getX(), origin.getZ()); WizardryAntiqueAtlasIntegration.markObelisk(world, origin.getX(), origin.getZ());
@@ -54,7 +54,7 @@ public class WorldGenShrine extends WorldGenSurfaceStructure {
ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo( ITemplateProcessor processor = (w, p, i) -> i.blockState.getBlock() instanceof BlockRunestone ? new Template.BlockInfo(
i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i; i.pos, i.blockState.withProperty(BlockRunestone.ELEMENT, element), i.tileentityData) : i;
template.addBlocksToWorld(world, origin, processor, settings, 2); template.addBlocksToWorld(world, origin, processor, settings, 2 | 16);
WizardryAntiqueAtlasIntegration.markShrine(world, origin.getX(), origin.getZ()); WizardryAntiqueAtlasIntegration.markShrine(world, origin.getX(), origin.getZ());
@@ -45,12 +45,12 @@ public abstract class WorldGenSurfaceStructure extends WorldGenWizardryStructure
protected BlockPos attemptPosition(Template template, PlacementSettings settings, Random random, World world, protected BlockPos attemptPosition(Template template, PlacementSettings settings, Random random, World world,
int chunkX, int chunkZ, String structureFile){ int chunkX, int chunkZ, String structureFile){
// Offset by (8, 8) to minimise cascading worldgen lag BlockPos size = template.transformedSize(settings.getRotation());
// Offset by (8, 8) to minimise cascading worldgen lag, MINUS half the width of the structure (important!)
// See https://www.reddit.com/r/feedthebeast/cowmments/5x0twz/investigating_extreme_worldgen_lag/?ref=share&ref_source=embed&utm_content=title&utm_medium=post_embed&utm_name=c07cbb545f74487793783012794733d8&utm_source=embedly&utm_term=5x0twz // See https://www.reddit.com/r/feedthebeast/cowmments/5x0twz/investigating_extreme_worldgen_lag/?ref=share&ref_source=embed&utm_content=title&utm_medium=post_embed&utm_name=c07cbb545f74487793783012794733d8&utm_source=embedly&utm_term=5x0twz
// Multiplying and left-shifting are identical but it's good practice to bitshift here I guess // Multiplying and left-shifting are identical but it's good practice to bitshift here I guess
BlockPos origin = new BlockPos(8 + (chunkX << 4) + random.nextInt(16), 0, 8 + (chunkZ << 4) + random.nextInt(16)); BlockPos origin = new BlockPos((chunkX << 4) + random.nextInt(16) + 8 - size.getX()/2, 0, (chunkZ << 4) + random.nextInt(16) + 8 - size.getZ()/2);
BlockPos size = template.transformedSize(settings.getRotation());
// Estimate a starting height for searching for the floor // Estimate a starting height for searching for the floor
BlockPos centre = world.getTopSolidOrLiquidBlock(new BlockPos(origin.add(size.getX()/2, 0, size.getZ()/2))); BlockPos centre = world.getTopSolidOrLiquidBlock(new BlockPos(origin.add(size.getX()/2, 0, size.getZ()/2)));
@@ -150,6 +150,9 @@ public abstract class WorldGenSurfaceStructure extends WorldGenWizardryStructure
for(int y1 = boundingBox.minY - border; y1 <= y + border; y1++){ for(int y1 = boundingBox.minY - border; y1 <= y + border; y1++){
for(int z = boundingBox.minZ - border; z <= boundingBox.maxZ + border; z++){ for(int z = boundingBox.minZ - border; z <= boundingBox.maxZ + border; z++){
BlockPos pos = new BlockPos(x, y1, z); BlockPos pos = new BlockPos(x, y1, z);
// Skip blocks that haven't been generated yet
// If you think about it, there can't possibly be floating trees in unloaded chunks anyway
if(!world.isBlockLoaded(pos)) continue;
if(world.getBlockState(pos).getBlock() instanceof BlockLeaves) leaves.add(pos); if(world.getBlockState(pos).getBlock() instanceof BlockLeaves) leaves.add(pos);
} }
} }
@@ -96,7 +96,7 @@ public class WorldGenUndergroundLibraryRuins extends WorldGenUndergroundStructur
} }
); );
template.addBlocksToWorld(world, origin, processor, settings, 2); template.addBlocksToWorld(world, origin, processor, settings, 2 | 16);
WizardryAntiqueAtlasIntegration.markLibrary(world, origin.getX(), origin.getZ()); WizardryAntiqueAtlasIntegration.markLibrary(world, origin.getX(), origin.getZ());
} }
@@ -25,9 +25,13 @@ public abstract class WorldGenUndergroundStructure extends WorldGenWizardryStruc
@Override @Override
protected BlockPos attemptPosition(Template template, PlacementSettings settings, Random random, World world, int chunkX, int chunkZ, String structureFile){ protected BlockPos attemptPosition(Template template, PlacementSettings settings, Random random, World world, int chunkX, int chunkZ, String structureFile){
BlockPos origin = new BlockPos(8 + (chunkX << 4) + random.nextInt(16), 20 + random.nextInt(40), 8 + (chunkZ << 4) + random.nextInt(16));
BlockPos size = template.transformedSize(settings.getRotation()); BlockPos size = template.transformedSize(settings.getRotation());
// Offset by (8, 8) to minimise cascading worldgen lag, MINUS half the width of the structure (important!)
// See https://www.reddit.com/r/feedthebeast/cowmments/5x0twz/investigating_extreme_worldgen_lag/?ref=share&ref_source=embed&utm_content=title&utm_medium=post_embed&utm_name=c07cbb545f74487793783012794733d8&utm_source=embedly&utm_term=5x0twz
// Multiplying and left-shifting are identical but it's good practice to bitshift here I guess
BlockPos origin = new BlockPos((chunkX << 4) + random.nextInt(16) + 8 - size.getX()/2, 20 + random.nextInt(40), (chunkZ << 4) + random.nextInt(16) + 8 - size.getZ()/2);
BlockPos corner = origin.add(size.getX(), 1, size.getZ()); // Need not iterate through everything BlockPos corner = origin.add(size.getX(), 1, size.getZ()); // Need not iterate through everything
// Criteria for a valid position: // Criteria for a valid position:
@@ -101,7 +101,7 @@ public class WorldGenWizardTower extends WorldGenSurfaceStructure {
(w, p, i) -> {if(i.blockState.getBlock() != Blocks.AIR) blocksPlaced.add(p); return i;} (w, p, i) -> {if(i.blockState.getBlock() != Blocks.AIR) blocksPlaced.add(p); return i;}
); );
template.addBlocksToWorld(world, origin, processor, settings, 2); template.addBlocksToWorld(world, origin, processor, settings, 2 | 16);
WizardryAntiqueAtlasIntegration.markTower(world, origin.getX(), origin.getZ()); WizardryAntiqueAtlasIntegration.markTower(world, origin.getX(), origin.getZ());