fixes a fundamental issue with Regions that causes heightmap lookups to be incorrectly offset by the Region border size
This commit is contained in:
parent
5adfa887a4
commit
c344ddb137
2
Noise2D
2
Noise2D
@ -1 +1 @@
|
||||
Subproject commit d48538cb76877d65ba67dcadf61cb36c47516419
|
||||
Subproject commit 0bbb025ead269860fe3a41dcb95f04c356164970
|
@ -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;
|
||||
}
|
||||
|
@ -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<Decorator> 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<ChunkReader> 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;
|
||||
|
@ -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) {
|
||||
|
@ -62,8 +62,12 @@ public class WorldGeneratorFactory implements Supplier<WorldGenerator> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -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<Terrain> getCell(int x, int z) {
|
||||
Cell<Terrain> 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;
|
||||
}
|
||||
}
|
@ -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))));
|
||||
}
|
||||
}
|
||||
|
@ -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<Biome, List<Decorator>> 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<Terrain> 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 {
|
||||
|
@ -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)];
|
||||
}
|
||||
|
@ -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<CommandSource> 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<CommandSource> context) throws CommandSyntaxException {
|
||||
// get the generator's context
|
||||
TerraContext terraContext = getContext(context).orElseThrow(() -> createException(
|
||||
|
Loading…
Reference in New Issue
Block a user