From c344ddb1372d6002c29be1cba708ec499cc40250 Mon Sep 17 00:00:00 2001 From: dags- Date: Mon, 9 Mar 2020 20:30:27 +0000 Subject: [PATCH] fixes a fundamental issue with Regions that causes heightmap lookups to be incorrectly offset by the Region border size --- Noise2D | 2 +- .../terraforged/core/filter/Steepness.java | 12 +++-- .../com/terraforged/core/region/Region.java | 23 +++------- .../terraforged/core/world/WorldFilters.java | 4 +- .../core/world/WorldGeneratorFactory.java | 6 ++- .../core/world/heightmap/WorldLookup.java | 44 +++++++++++++++++++ .../com/terraforged/mod/biome/Marshland.java | 14 ++++++ .../mod/biome/provider/BiomeProvider.java | 15 +++---- .../terraforged/mod/chunk/TerraContainer.java | 4 +- .../terraforged/mod/command/TerraCommand.java | 24 ++++++++++ 10 files changed, 113 insertions(+), 35 deletions(-) create mode 100644 TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java diff --git a/Noise2D b/Noise2D index d48538c..0bbb025 160000 --- a/Noise2D +++ b/Noise2D @@ -1 +1 @@ -Subproject commit d48538cb76877d65ba67dcadf61cb36c47516419 +Subproject commit 0bbb025ead269860fe3a41dcb95f04c356164970 diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java index ea7cc82..be06092 100644 --- a/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java +++ b/TerraForgedCore/src/main/java/com/terraforged/core/filter/Steepness.java @@ -1,5 +1,5 @@ /* - * + * * MIT License * * Copyright (c) 2020 TerraForged @@ -35,7 +35,11 @@ public class Steepness implements Filter, Filter.Visitor { private final Terrains terrains; public Steepness(Terrains terrains) { - this(1, 16F, terrains); + this(2, 16F, terrains); + } + + public Steepness(float scaler, Terrains terrains) { + this(2, scaler, terrains); } public Steepness(int radius, float scaler, Terrains terrains) { @@ -52,8 +56,8 @@ public class Steepness implements Filter, Filter.Visitor { @Override public void visit(Filterable cellMap, Cell cell, int cx, int cz) { float totalHeightDif = 0F; - for (int dz = -1; dz <= 2; dz++) { - for (int dx = -1; dx <= 2; dx++) { + for (int dz = -radius; dz <= radius; dz++) { + for (int dx = -radius; dx <= radius; dx++) { if (dx == 0 && dz == 0) { continue; } diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java b/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java index 592411c..1daab6b 100644 --- a/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java +++ b/TerraForgedCore/src/main/java/com/terraforged/core/region/Region.java @@ -143,8 +143,8 @@ public class Region implements Extent { } public void generateZoom(Heightmap heightmap, float offsetX, float offsetZ, float zoom, Batcher batcher) { - float translateX = offsetX - ((blockSize.total * zoom) / 2F); - float translateZ = offsetZ - ((blockSize.total * zoom) / 2F); + float translateX = offsetX - ((blockSize.size * zoom) / 2F); + float translateZ = offsetZ - ((blockSize.size * zoom) / 2F); for (int cz = 0; cz < chunkSize.total; cz++) { for (int cx = 0; cx < chunkSize.total; cx++) { int index = chunkSize.indexOf(cx, cz); @@ -190,8 +190,8 @@ public class Region implements Extent { } public void decorateZoom(Collection decorators, float offsetX, float offsetZ, float zoom) { - float translateX = offsetX - ((blockSize.total * zoom) / 2F); - float translateZ = offsetZ - ((blockSize.total * zoom) / 2F); + float translateX = offsetX - ((blockSize.size * zoom) / 2F); + float translateZ = offsetZ - ((blockSize.size * zoom) / 2F); for (int cz = 0; cz < chunkSize.total; cz++) { for (int cx = 0; cx < chunkSize.total; cx++) { int index = chunkSize.indexOf(cx, cz); @@ -205,17 +205,6 @@ public class Region implements Extent { }); } } - - -// for (int dz = 0; dz < blockSize.total; dz++) { -// for (int dx = 0; dx < blockSize.total; dx++) { -// int index = blockSize.indexOf(dx, dz); -// GenCell cell = blocks[index]; -// for (Decorator decorator : decorators) { -// decorator.apply(cell, getBlockX() + translateX + dx, getBlockZ() + translateZ + dz); -// } -// } -// } } public void iterate(Consumer consumer) { @@ -303,8 +292,8 @@ public class Region implements Extent { this.regionBlockX = regionChunkX << 4; this.regionBlockZ = regionChunkZ << 4; // the real coordinate of this chunk within the world - this.chunkX = Region.this.chunkX + regionChunkX; - this.chunkZ = Region.this.chunkZ + regionChunkZ; + this.chunkX = Region.this.chunkX + regionChunkX - chunkSize.border; + this.chunkZ = Region.this.chunkZ + regionChunkZ - chunkSize.border; // the real block coordinate of this chunk within the world this.blockX = chunkX << 4; this.blockZ = chunkZ << 4; diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java index 879debc..5f78f94 100644 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java +++ b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldFilters.java @@ -1,5 +1,5 @@ /* - * + * * MIT License * * Copyright (c) 2020 TerraForged @@ -45,7 +45,7 @@ public class WorldFilters { this.settings = context.settings.filters; this.erosion = new Erosion(context.settings, context.levels); this.smoothing = new Smoothing(context.settings, context.levels); - this.steepness = new Steepness(1, 10F, context.terrain); + this.steepness = new Steepness(2, 10F, context.terrain); } public void apply(Region region) { diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java index 86a5801..a0500ca 100644 --- a/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java +++ b/TerraForgedCore/src/main/java/com/terraforged/core/world/WorldGeneratorFactory.java @@ -62,8 +62,12 @@ public class WorldGeneratorFactory implements Supplier { return decorators; } + public WorldFilters getFilters() { + return new WorldFilters(context); + } + @Override public WorldGenerator get() { - return new WorldGenerator(heightmap, decorators, new WorldFilters(context)); + return new WorldGenerator(heightmap, decorators, getFilters()); } } diff --git a/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java new file mode 100644 index 0000000..1869c0d --- /dev/null +++ b/TerraForgedCore/src/main/java/com/terraforged/core/world/heightmap/WorldLookup.java @@ -0,0 +1,44 @@ +package com.terraforged.core.world.heightmap; + +import com.terraforged.core.cell.Cell; +import com.terraforged.core.world.GeneratorContext; +import com.terraforged.core.world.WorldDecorators; +import com.terraforged.core.world.WorldGeneratorFactory; +import com.terraforged.core.world.decorator.Decorator; +import com.terraforged.core.world.terrain.Terrain; + +public class WorldLookup { + + private final float waterLevel; + private final float beachLevel; + private final Heightmap heightmap; + private final WorldDecorators decorators; + private final GeneratorContext context; + + public WorldLookup(WorldGeneratorFactory factory, GeneratorContext context) { + this.context = context; + this.heightmap = factory.getHeightmap(); + this.decorators = factory.getDecorators(); + this.waterLevel = context.levels.water; + this.beachLevel = context.levels.water(5); + } + + public Cell getCell(int x, int z) { + Cell cell = new Cell<>(); + + heightmap.apply(cell, x, z); + + // approximation - actual beaches depend on steepness but that's too expensive to calculate + if (cell.tag == context.terrain.coast && cell.value > waterLevel && cell.value <= beachLevel) { + cell.tag = context.terrain.beach; + } + + for (Decorator decorator : decorators.getDecorators()) { + if (decorator.apply(cell, x, z)) { + break; + } + } + + return cell; + } +} diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java index a988794..35e77b3 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/Marshland.java @@ -31,6 +31,11 @@ import net.minecraft.entity.EntityType; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biomes; import net.minecraft.world.biome.DefaultBiomeFeatures; +import net.minecraft.world.gen.GenerationStage; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.placement.FrequencyConfig; +import net.minecraft.world.gen.placement.HeightWithChanceConfig; +import net.minecraft.world.gen.placement.Placement; import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder; public class Marshland extends BiomeVariant { @@ -51,6 +56,7 @@ public class Marshland extends BiomeVariant { DefaultBiomeFeatures.addGrass(this); DefaultBiomeFeatures.addVeryDenseGrass(this); DefaultBiomeFeatures.addReedsAndPumpkins(this); + Marshland.addSwampVegetation(this); DefaultBiomeFeatures.addFreezeTopLayer(this); this.addSpawn(EntityClassification.CREATURE, new SpawnListEntry(EntityType.SHEEP, 12, 4, 4)); this.addSpawn(EntityClassification.CREATURE, new SpawnListEntry(EntityType.PIG, 10, 4, 4)); @@ -83,4 +89,12 @@ public class Marshland extends BiomeVariant { public Biome getBase() { return Biomes.SWAMP; } + + private static void addSwampVegetation(Biome biome) { + biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.LILY_PAD_CONFIG).withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(4)))); + biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.DEAD_BUSH_CONFIG).withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(1)))); + biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.LILY_PAD_CONFIG).withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(4)))); + biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.BROWN_MUSHROOM_CONFIG).withPlacement(Placement.COUNT_CHANCE_HEIGHTMAP.configure(new HeightWithChanceConfig(8, 0.25F)))); + biome.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Feature.RANDOM_PATCH.withConfiguration(DefaultBiomeFeatures.RED_MUSHROOM_CONFIG).withPlacement(Placement.COUNT_CHANCE_HEIGHTMAP_DOUBLE.configure(new HeightWithChanceConfig(8, 0.125F)))); + } } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java index 9d5c405..edb2b74 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/biome/provider/BiomeProvider.java @@ -29,6 +29,7 @@ import com.google.common.collect.Sets; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.core.world.decorator.Decorator; +import com.terraforged.core.world.heightmap.WorldLookup; import com.terraforged.core.world.terrain.Terrain; import com.terraforged.mod.biome.map.BiomeMap; import com.terraforged.mod.biome.modifier.BiomeModifierManager; @@ -52,23 +53,22 @@ public class BiomeProvider extends AbstractBiomeProvider { private final BiomeMap biomeMap; private final TerraContext context; + private final WorldLookup worldLookup; private final BiomeModifierManager modifierManager; private final Map> decorators = new HashMap<>(); public BiomeProvider(TerraContext context) { this.context = context; this.biomeMap = BiomeHelper.getDefaultBiomeMap(); + this.worldLookup = new WorldLookup(context.factory, context); this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy()); } @Override public Biome getNoiseBiome(int x, int y, int z) { - // I don't know why +24, just seems to provide slightly more accurate results - x = (x << 2) + 24; - z = (z << 2) + 24; - Cell cell = new Cell<>(); - context.heightmap.apply(cell, x, z); - return getBiome(cell, x, z); + x = (x << 2); + z = (z << 2); + return getBiome(worldLookup.getCell(x, z), x, z); } @Override @@ -171,8 +171,7 @@ public class BiomeProvider extends AbstractBiomeProvider { } private static boolean overridesRiver(Biome biome) { - return biome.getCategory() == Biome.Category.SWAMP - || biome.getCategory() == Biome.Category.JUNGLE; + return biome.getCategory() == Biome.Category.SWAMP || biome.getCategory() == Biome.Category.JUNGLE; } private static class SearchContext { diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java index ba69e83..5610d1e 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/chunk/TerraContainer.java @@ -114,8 +114,8 @@ public class TerraContainer extends BiomeContainer { for (int dy = 0; dy < 64; dy++) { for (int dz = 0; dz < 4; dz++) { for (int dx = 0; dx < 4; dx++) { - int x = 2 + (dx * 4); - int z = 2 + (dz * 4); + int x = dx * 4; + int z = dz * 4; int index = indexOf(dx, dy, dz); biomes[index] = surfaceBiomeCache[indexOf(x, z)]; } diff --git a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java b/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java index 415f187..cddedc5 100644 --- a/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java +++ b/TerraForgedMod/src/main/java/com/terraforged/mod/command/TerraCommand.java @@ -49,6 +49,7 @@ import com.terraforged.mod.data.DataGen; import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; @@ -60,6 +61,7 @@ import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; import net.minecraft.world.IWorldReader; import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.ColumnFuzzedBiomeMagnifier; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.ChunkGenerator; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -92,6 +94,8 @@ public class TerraCommand { .then(Commands.literal("data") .then(Commands.literal("dump") .executes(TerraCommand::dump))) + .then(Commands.literal("debug") + .executes(TerraCommand::debugBiome)) .then(Commands.literal("locate") .then(Commands.argument("biome", BiomeArgType.biome()) .executes(TerraCommand::findBiome) @@ -132,6 +136,26 @@ public class TerraCommand { return Command.SINGLE_SUCCESS; } + private static int debugBiome(CommandContext context) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().asPlayer(); + BlockPos position = player.getPosition(); + int x = position.getX(); + int y = position.getY(); + int z = position.getZ(); + + long seed = player.getServerWorld().getSeed(); + Biome actual = player.getServerWorld().getBiome(position); + Biome biome2 = ColumnFuzzedBiomeMagnifier.INSTANCE.getBiome(seed, x, 0, z, player.getServerWorld().getWorldServer().getChunkProvider().generator.getBiomeProvider()); + + context.getSource().sendFeedback(new StringTextComponent( + "Actual Biome = " + actual.getRegistryName() + + "\nLookup Biome = " + biome2.getRegistryName()), + false + ); + + return Command.SINGLE_SUCCESS; + } + private static int findTerrain(CommandContext context) throws CommandSyntaxException { // get the generator's context TerraContext terraContext = getContext(context).orElseThrow(() -> createException(