From 282817009e8d2f85811f8c84f2aa355ab77ca1c1 Mon Sep 17 00:00:00 2001 From: dags- Date: Sat, 6 Jun 2020 17:39:10 +0100 Subject: [PATCH] - fix ArrayPool leaking resources to multiple threads - remove ChunkReader from biome container - hopefully greatly improved memory efficiency by pooling Cell & Chunk arrays - added custom snow placer that places snow beneath leaves as well as on top --- .../java/com/terraforged/TerraForgedMod.java | 2 + .../biome/modifier/BiomeModifierManager.java | 1 + .../biome/modifier/MushroomModifier.java | 23 ++++++ .../chunk/TerraChunkGenerator.java | 29 ++++++-- .../terraforged/chunk/TerraSetupFactory.java | 9 +++ .../chunk/generator/BiomeGenerator.java | 20 ++++-- .../chunk/generator/FeatureGenerator.java | 21 ++++-- .../chunk/generator/SurfaceGenerator.java | 39 +++++----- .../chunk/generator/TerrainGenerator.java | 25 ++++--- .../chunk/util/TerraContainer.java | 28 +++----- .../feature/context/ChanceContext.java | 38 +++++----- .../context/ContextSelectorFeature.java | 2 +- .../decorator/poisson/BiomeVariance.java | 23 ++---- .../decorator/poisson/PoissonConfig.java | 5 +- .../decorator/poisson/PoissonDecorator.java | 2 +- .../feature/feature/FreezeLayer.java | 72 +++++++++++++++++++ 16 files changed, 230 insertions(+), 109 deletions(-) create mode 100644 src/main/java/com/terraforged/biome/modifier/MushroomModifier.java create mode 100644 src/main/java/com/terraforged/feature/feature/FreezeLayer.java diff --git a/src/main/java/com/terraforged/TerraForgedMod.java b/src/main/java/com/terraforged/TerraForgedMod.java index bedf090..634afa8 100644 --- a/src/main/java/com/terraforged/TerraForgedMod.java +++ b/src/main/java/com/terraforged/TerraForgedMod.java @@ -31,6 +31,7 @@ import com.terraforged.data.DataGen; import com.terraforged.feature.context.ContextSelectorFeature; import com.terraforged.feature.decorator.poisson.PoissonAtSurface; import com.terraforged.feature.feature.DiskFeature; +import com.terraforged.feature.feature.FreezeLayer; import com.terraforged.fm.template.TemplateManager; import com.terraforged.settings.SettingsHelper; import com.terraforged.util.DataPackFinder; @@ -83,6 +84,7 @@ public class TerraForgedMod { Log.info("Registering features"); TemplateManager.register(event); event.getRegistry().register(DiskFeature.INSTANCE); + event.getRegistry().register(FreezeLayer.INSTANCE); event.getRegistry().register(ContextSelectorFeature.INSTANCE); } diff --git a/src/main/java/com/terraforged/biome/modifier/BiomeModifierManager.java b/src/main/java/com/terraforged/biome/modifier/BiomeModifierManager.java index bec1784..25a8958 100644 --- a/src/main/java/com/terraforged/biome/modifier/BiomeModifierManager.java +++ b/src/main/java/com/terraforged/biome/modifier/BiomeModifierManager.java @@ -50,6 +50,7 @@ public class BiomeModifierManager implements BiomeModifier, ModifierManager { modifiers.add(new BeachModifier(biomes, context)); modifiers.add(new DesertColorModifier(desertBiomes)); modifiers.add(new SandBiomeModifier(context)); + modifiers.add(new MushroomModifier()); Collections.sort(modifiers); this.biomeModifiers = modifiers; } diff --git a/src/main/java/com/terraforged/biome/modifier/MushroomModifier.java b/src/main/java/com/terraforged/biome/modifier/MushroomModifier.java new file mode 100644 index 0000000..97a30c2 --- /dev/null +++ b/src/main/java/com/terraforged/biome/modifier/MushroomModifier.java @@ -0,0 +1,23 @@ +package com.terraforged.biome.modifier; + +import com.terraforged.api.biome.modifier.BiomeModifier; +import com.terraforged.core.cell.Cell; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; + +public class MushroomModifier implements BiomeModifier { + @Override + public int priority() { + return 0; + } + + @Override + public boolean test(Biome biome) { + return biome == Biomes.MUSHROOM_FIELD_SHORE; + } + + @Override + public Biome modify(Biome in, Cell cell, int x, int z) { + return Biomes.MUSHROOM_FIELDS; + } +} diff --git a/src/main/java/com/terraforged/chunk/TerraChunkGenerator.java b/src/main/java/com/terraforged/chunk/TerraChunkGenerator.java index b3947e1..78f4431 100644 --- a/src/main/java/com/terraforged/chunk/TerraChunkGenerator.java +++ b/src/main/java/com/terraforged/chunk/TerraChunkGenerator.java @@ -176,13 +176,14 @@ public class TerraChunkGenerator extends ChunkGenerator { public final int func_222529_a(int x, int z, Heightmap.Type type) { int chunkX = Size.blockToChunk(x); int chunkZ = Size.blockToChunk(z); - ChunkReader chunk = getChunkReader(chunkX, chunkZ); - Cell cell = chunk.getCell(x, z); - int level = context.levels.scale(cell.value) + 1; - if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) { - return level; + try (ChunkReader chunk = getChunkReader(chunkX, chunkZ)) { + Cell cell = chunk.getCell(x, z); + int level = context.levels.scale(cell.value) + 1; + if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) { + return level; + } + return Math.max(getSeaLevel(), level); } - return Math.max(getSeaLevel(), level); } @Override @@ -260,4 +261,20 @@ public class TerraChunkGenerator extends ChunkGenerator { public final ChunkReader getChunkReader(int chunkX, int chunkZ) { return regionCache.getChunk(chunkX, chunkZ); } + + public static ChunkReader getChunk(IWorld world, ChunkGenerator generator) { + if (generator instanceof TerraChunkGenerator) { + TerraChunkGenerator terra = (TerraChunkGenerator) generator; + if (world instanceof IChunk) { + IChunk chunk = (IChunk) world; + return terra.getChunkReader(chunk.getPos().x, chunk.getPos().z); + } + + if (world instanceof WorldGenRegion) { + WorldGenRegion region = (WorldGenRegion) world; + return terra.getChunkReader(region.getMainChunkX(), region.getMainChunkZ()); + } + } + return null; + } } diff --git a/src/main/java/com/terraforged/chunk/TerraSetupFactory.java b/src/main/java/com/terraforged/chunk/TerraSetupFactory.java index 1a2f64a..0165c25 100644 --- a/src/main/java/com/terraforged/chunk/TerraSetupFactory.java +++ b/src/main/java/com/terraforged/chunk/TerraSetupFactory.java @@ -15,6 +15,7 @@ import com.terraforged.chunk.column.post.LayerDecorator; import com.terraforged.chunk.column.post.SnowEroder; import com.terraforged.feature.BlockDataManager; import com.terraforged.feature.Matchers; +import com.terraforged.feature.feature.FreezeLayer; import com.terraforged.fm.FeatureManager; import com.terraforged.fm.data.DataManager; import com.terraforged.fm.matcher.biome.BiomeMatcher; @@ -24,6 +25,7 @@ import com.terraforged.fm.predicate.DeepWater; import com.terraforged.fm.predicate.FeaturePredicate; import com.terraforged.fm.predicate.MinHeight; import com.terraforged.fm.structure.StructureManager; +import com.terraforged.fm.transformer.FeatureTransformer; import com.terraforged.material.geology.GeoManager; import com.terraforged.util.setup.SetupHooks; import net.minecraft.world.biome.Biome; @@ -90,6 +92,13 @@ public class TerraSetupFactory { if (context.terraSettings.features.customBiomeFeatures) { // remove default trees from river biomes since forests can go up to the edge of rivers modifiers.getPredicates().add(BiomeMatcher.of(Biome.Category.RIVER), Matchers.tree(), FeaturePredicate.DENY); + + // places snow layers below and on top of trees + modifiers.getTransformers().add( + BiomeMatcher.ANY, + FeatureMatcher.of(Feature.FREEZE_TOP_LAYER), + FeatureTransformer.replace(Feature.FREEZE_TOP_LAYER, FreezeLayer.INSTANCE) + ); } // block ugly features diff --git a/src/main/java/com/terraforged/chunk/generator/BiomeGenerator.java b/src/main/java/com/terraforged/chunk/generator/BiomeGenerator.java index 208632c..4484765 100644 --- a/src/main/java/com/terraforged/chunk/generator/BiomeGenerator.java +++ b/src/main/java/com/terraforged/chunk/generator/BiomeGenerator.java @@ -1,7 +1,9 @@ package com.terraforged.chunk.generator; +import com.terraforged.biome.provider.BiomeProvider; import com.terraforged.chunk.TerraChunkGenerator; import com.terraforged.chunk.util.TerraContainer; +import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.world.terrain.decorator.Decorator; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.biome.Biome; @@ -10,23 +12,27 @@ import net.minecraft.world.chunk.IChunk; public class BiomeGenerator { private final TerraChunkGenerator generator; + private final BiomeProvider biomeProvider; public BiomeGenerator(TerraChunkGenerator generator) { this.generator = generator; + this.biomeProvider = generator.getBiomeProvider(); } public void generateBiomes(IChunk chunk) { ChunkPos pos = chunk.getPos(); - TerraContainer container = TerraContainer.getOrCreate(chunk, generator); - // apply chunk-local heightmap modifications - preProcess(pos, container); + try (ChunkReader reader = generator.getChunkReader(pos.x, pos.z)) { + TerraContainer container = TerraContainer.create(reader, generator.getBiomeProvider()); + // apply chunk-local heightmap modifications + preProcess(reader, container); + } } - private void preProcess(ChunkPos pos, TerraContainer container) { - container.getChunkReader().iterate((cell, dx, dz) -> { - Biome biome = container.getBiome(dx, dz); + private void preProcess(ChunkReader reader, TerraContainer biomes) { + reader.iterate((cell, dx, dz) -> { + Biome biome = biomes.getBiome(dx, dz); for (Decorator decorator : generator.getBiomeProvider().getDecorators(biome)) { - if (decorator.apply(cell, pos.getXStart() + dx, pos.getZStart() + dz)) { + if (decorator.apply(cell, reader.getBlockX() + dx, reader.getBlockZ() + dz)) { return; } } diff --git a/src/main/java/com/terraforged/chunk/generator/FeatureGenerator.java b/src/main/java/com/terraforged/chunk/generator/FeatureGenerator.java index fdcee66..37e52d0 100644 --- a/src/main/java/com/terraforged/chunk/generator/FeatureGenerator.java +++ b/src/main/java/com/terraforged/chunk/generator/FeatureGenerator.java @@ -29,10 +29,11 @@ public class FeatureGenerator { int chunkX = region.getMainChunkX(); int chunkZ = region.getMainChunkZ(); IChunk chunk = region.getChunk(chunkX, chunkZ); - TerraContainer container = TerraContainer.getOrCreate(chunk, generator); - ChunkReader chunkReader = generator.getChunkReader(chunkX, chunkZ); - Biome biome = container.getFeatureBiome(chunkReader); + ChunkReader reader = generator.getChunkReader(chunkX, chunkZ); + TerraContainer container = TerraContainer.getOrCreate(chunk, reader, generator.getBiomeProvider()); + + Biome biome = container.getFeatureBiome(reader); DecoratorContext context = generator.getContext().decorator(chunk); IWorld regionFix = new RegionFix(region, generator); @@ -42,15 +43,21 @@ public class FeatureGenerator { generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos); // run post processes on chunk - postProcess(chunkReader, container, context); + postProcess(reader, container, context); - // bake biome array & discard gen data + // bake biome array ((ChunkPrimer) chunk).func_225548_a_(container.bakeBiomes(Environment.isVanillaBiomes())); + + // close the current chunk reader + reader.close(); + + // mark chunk disposed as this is the last usage of the reader + reader.dispose(); } - private void postProcess(ChunkReader chunk, TerraContainer container, DecoratorContext context) { + private void postProcess(ChunkReader reader, TerraContainer container, DecoratorContext context) { List decorators = generator.getPostProcessors(); - container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { + reader.iterate(context, (cell, dx, dz, ctx) -> { int px = ctx.blockX + dx; int pz = ctx.blockZ + dz; int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz); diff --git a/src/main/java/com/terraforged/chunk/generator/SurfaceGenerator.java b/src/main/java/com/terraforged/chunk/generator/SurfaceGenerator.java index 07ffa09..9e9ac98 100644 --- a/src/main/java/com/terraforged/chunk/generator/SurfaceGenerator.java +++ b/src/main/java/com/terraforged/chunk/generator/SurfaceGenerator.java @@ -6,6 +6,7 @@ import com.terraforged.api.chunk.surface.SurfaceContext; import com.terraforged.chunk.TerraChunkGenerator; import com.terraforged.chunk.util.FastChunk; import com.terraforged.chunk.util.TerraContainer; +import com.terraforged.core.region.chunk.ChunkReader; import net.minecraft.util.SharedSeedRandom; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.Heightmap; @@ -24,30 +25,32 @@ public class SurfaceGenerator { } public final void generateSurface(WorldGenRegion world, IChunk chunk) { - TerraContainer container = TerraContainer.getOrCreate(chunk, generator); - ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk)); + try (ChunkReader reader = generator.getChunkReader(chunk.getPos().x, chunk.getPos().z)) { + TerraContainer container = TerraContainer.getOrCreate(chunk, reader, generator.getBiomeProvider()); + ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk)); - try (SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings())) { - container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { - int px = ctx.blockX + dx; - int pz = ctx.blockZ + dz; - int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz); + try (SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings())) { + reader.iterate(context, (cell, dx, dz, ctx) -> { + int px = ctx.blockX + dx; + int pz = ctx.blockZ + dz; + int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz); - ctx.buffer.setSurfaceLevel(top); + ctx.buffer.setSurfaceLevel(top); - ctx.cell = cell; - ctx.biome = container.getBiome(dx, dz); - ctx.noise = getSurfaceNoise(px, pz) * 15D; + ctx.cell = cell; + ctx.biome = container.getBiome(dx, dz); + ctx.noise = getSurfaceNoise(px, pz) * 15D; - generator.getSurfaceManager().getSurface(ctx).buildSurface(px, pz, top, ctx); + generator.getSurfaceManager().getSurface(ctx).buildSurface(px, pz, top, ctx); - int py = ctx.levels.scale(cell.value); - for (ColumnDecorator processor : generator.getBaseDecorators()) { - processor.decorate(ctx.buffer, ctx, px, py, pz); - } - }); + int py = ctx.levels.scale(cell.value); + for (ColumnDecorator processor : generator.getBaseDecorators()) { + processor.decorate(ctx.buffer, ctx, px, py, pz); + } + }); - FastChunk.updateWGHeightmaps(chunk, context.pos); + FastChunk.updateWGHeightmaps(chunk, context.pos); + } } } diff --git a/src/main/java/com/terraforged/chunk/generator/TerrainGenerator.java b/src/main/java/com/terraforged/chunk/generator/TerrainGenerator.java index 1377526..58b4457 100644 --- a/src/main/java/com/terraforged/chunk/generator/TerrainGenerator.java +++ b/src/main/java/com/terraforged/chunk/generator/TerrainGenerator.java @@ -5,6 +5,7 @@ import com.terraforged.chunk.TerraChunkGenerator; import com.terraforged.chunk.column.ChunkPopulator; import com.terraforged.chunk.util.FastChunk; import com.terraforged.chunk.util.TerraContainer; +import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.feature.TerrainHelper; import com.terraforged.world.climate.Climate; import com.terraforged.world.heightmap.Levels; @@ -29,17 +30,19 @@ public class TerrainGenerator { } public final void generateTerrain(IWorld world, IChunk chunk) { - TerraContainer container = TerraContainer.getOrCreate(chunk, generator); - try (DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), levels, terrain, climate)) { - container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> { - int px = ctx.blockX + dx; - int pz = ctx.blockZ + dz; - int py = ctx.levels.scale(cell.value); - ctx.cell = cell; - ctx.biome = container.getNoiseBiome(dx, world.getSeaLevel(), dz); - ChunkPopulator.INSTANCE.decorate(ctx.chunk, ctx, px, py, pz); - }); - terrainHelper.flatten(world, chunk); + try (ChunkReader reader = generator.getChunkReader(chunk.getPos().x, chunk.getPos().z)) { + TerraContainer container = TerraContainer.getOrCreate(chunk, reader, generator.getBiomeProvider()); + try (DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), levels, terrain, climate)) { + reader.iterate(context, (cell, dx, dz, ctx) -> { + int px = ctx.blockX + dx; + int pz = ctx.blockZ + dz; + int py = ctx.levels.scale(cell.value); + ctx.cell = cell; + ctx.biome = container.getNoiseBiome(dx, world.getSeaLevel(), dz); + ChunkPopulator.INSTANCE.decorate(ctx.chunk, ctx, px, py, pz); + }); + terrainHelper.flatten(world, chunk); + } } } } diff --git a/src/main/java/com/terraforged/chunk/util/TerraContainer.java b/src/main/java/com/terraforged/chunk/util/TerraContainer.java index b271f20..a4da897 100644 --- a/src/main/java/com/terraforged/chunk/util/TerraContainer.java +++ b/src/main/java/com/terraforged/chunk/util/TerraContainer.java @@ -1,11 +1,10 @@ package com.terraforged.chunk.util; import com.terraforged.api.biome.BiomeVariant; -import com.terraforged.chunk.TerraChunkGenerator; +import com.terraforged.biome.provider.BiomeProvider; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.core.util.PosIterator; -import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.BiomeContainer; @@ -23,17 +22,11 @@ public class TerraContainer extends BiomeContainer { private final Biome[] biomes; private final Biome[] surface; - private final ChunkReader chunkReader; - public TerraContainer(Biome[] biomes, Biome[] surface, ChunkReader chunkReader) { + public TerraContainer(Biome[] biomes, Biome[] surface) { super(biomes); this.biomes = biomes; this.surface = surface; - this.chunkReader = chunkReader; - } - - public ChunkReader getChunkReader() { - return chunkReader; } public Biome getBiome(int x, int z) { @@ -68,28 +61,26 @@ public class TerraContainer extends BiomeContainer { return new BiomeContainer(biomes); } - public static TerraContainer getOrCreate(IChunk chunk, TerraChunkGenerator generator) { + public static TerraContainer getOrCreate(IChunk chunk, ChunkReader reader, BiomeProvider biomeProvider) { if (chunk.getBiomes() instanceof TerraContainer) { return (TerraContainer) chunk.getBiomes(); } else { - TerraContainer container = TerraContainer.create(generator, chunk.getPos()); + TerraContainer container = TerraContainer.create(reader, biomeProvider); ((ChunkPrimer) chunk).func_225548_a_(container); return container; } } - public static TerraContainer create(TerraChunkGenerator generator, ChunkPos pos) { - ChunkReader reader = generator.getChunkReader(pos.x, pos.z); - + public static TerraContainer create(ChunkReader chunkReader, BiomeProvider biomeProvider) { Biome[] biomes2D = new Biome[BIOMES_2D_SIZE]; Biome[] biomes3D = new Biome[BIOMES_3D_SIZE]; PosIterator iterator = PosIterator.area(0, 0, 16, 16); while (iterator.next()) { int dx = iterator.x(); int dz = iterator.z(); - int x = pos.getXStart() + dx; - int z = pos.getZStart() + dz; - Biome biome = generator.getBiomeProvider().getBiome(reader.getCell(dx, dz), x, z); + int x = chunkReader.getBlockX() + dx; + int z = chunkReader.getBlockZ() + dz; + Biome biome = biomeProvider.getBiome(chunkReader.getCell(dx, dz), x, z); biomes2D[indexOf(dx, dz)] = biome; if ((dx & 3) == 0 && (dz & 3) == 0) { for (int dy = 0; dy < 64; dy++) { @@ -97,8 +88,7 @@ public class TerraContainer extends BiomeContainer { } } } - - return new TerraContainer(biomes3D, biomes2D, reader); + return new TerraContainer(biomes3D, biomes2D); } private static int indexOf(int x, int z) { diff --git a/src/main/java/com/terraforged/feature/context/ChanceContext.java b/src/main/java/com/terraforged/feature/context/ChanceContext.java index 8bce18e..00aea2c 100644 --- a/src/main/java/com/terraforged/feature/context/ChanceContext.java +++ b/src/main/java/com/terraforged/feature/context/ChanceContext.java @@ -1,21 +1,22 @@ package com.terraforged.feature.context; +import com.terraforged.chunk.TerraChunkGenerator; import com.terraforged.chunk.fix.RegionDelegate; -import com.terraforged.chunk.util.TerraContainer; import com.terraforged.core.cell.Cell; import com.terraforged.core.concurrent.Resource; +import com.terraforged.core.concurrent.cache.SafeCloseable; import com.terraforged.core.concurrent.pool.ObjectPool; import com.terraforged.core.region.chunk.ChunkReader; import com.terraforged.world.heightmap.Levels; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; -import net.minecraft.world.biome.BiomeContainer; import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.WorldGenRegion; import java.util.Random; -public class ChanceContext { +public class ChanceContext implements SafeCloseable { private static final ObjectPool pool = new ObjectPool<>(10, ChanceContext::new); @@ -28,6 +29,14 @@ public class ChanceContext { private float total = 0F; private float[] buffer; + @Override + public void close() { + if (reader != null) { + reader.close(); + reader = null; + } + } + void setPos(BlockPos pos) { cell = reader.getCell(pos.getX(), pos.getZ()); } @@ -61,25 +70,16 @@ public class ChanceContext { return -1; } - public static Resource pooled(IWorld world) { - if (world instanceof RegionDelegate) { - Levels levels = new Levels(world.getMaxHeight(), world.getSeaLevel()); + public static Resource pooled(IWorld world, ChunkGenerator generator) { + if (generator instanceof TerraChunkGenerator && world instanceof RegionDelegate) { + TerraChunkGenerator terraGenerator = (TerraChunkGenerator) generator; + Levels levels = terraGenerator.getContext().levels; WorldGenRegion region = ((RegionDelegate) world).getRegion(); IChunk chunk = region.getChunk(region.getMainChunkX(), region.getMainChunkZ()); - return pooled(chunk, levels); - } - return null; - } - - public static Resource pooled(IChunk chunk, Levels levels) { - BiomeContainer container = chunk.getBiomes(); - if (container instanceof TerraContainer) { - ChunkReader reader = ((TerraContainer) container).getChunkReader(); Resource item = pool.get(); - ChanceContext context = item.get(); - context.chunk = chunk; - context.levels = levels; - context.reader = reader; + item.get().chunk = chunk; + item.get().levels = levels; + item.get().reader = terraGenerator.getChunkReader(chunk.getPos().x, chunk.getPos().z); return item; } return null; diff --git a/src/main/java/com/terraforged/feature/context/ContextSelectorFeature.java b/src/main/java/com/terraforged/feature/context/ContextSelectorFeature.java index 2047853..5c44c19 100644 --- a/src/main/java/com/terraforged/feature/context/ContextSelectorFeature.java +++ b/src/main/java/com/terraforged/feature/context/ContextSelectorFeature.java @@ -20,7 +20,7 @@ public class ContextSelectorFeature extends Feature { @Override public boolean place(IWorld world, ChunkGenerator generator, Random random, BlockPos pos, ContextSelectorConfig config) { - try (Resource item = ChanceContext.pooled(world)) { + try (Resource item = ChanceContext.pooled(world, generator)) { if (item == null) { return false; } diff --git a/src/main/java/com/terraforged/feature/decorator/poisson/BiomeVariance.java b/src/main/java/com/terraforged/feature/decorator/poisson/BiomeVariance.java index fd633c3..a337170 100644 --- a/src/main/java/com/terraforged/feature/decorator/poisson/BiomeVariance.java +++ b/src/main/java/com/terraforged/feature/decorator/poisson/BiomeVariance.java @@ -1,16 +1,13 @@ package com.terraforged.feature.decorator.poisson; -import com.terraforged.chunk.fix.RegionDelegate; -import com.terraforged.chunk.util.TerraContainer; +import com.terraforged.chunk.TerraChunkGenerator; import com.terraforged.core.cell.Cell; import com.terraforged.core.region.chunk.ChunkReader; import me.dags.noise.Module; import me.dags.noise.Source; import me.dags.noise.util.NoiseUtil; import net.minecraft.world.IWorld; -import net.minecraft.world.biome.BiomeContainer; -import net.minecraft.world.chunk.IChunk; -import net.minecraft.world.gen.WorldGenRegion; +import net.minecraft.world.gen.ChunkGenerator; public class BiomeVariance implements Module { @@ -32,19 +29,9 @@ public class BiomeVariance implements Module { return NoiseUtil.map(1 - cell.biomeEdge, MIN_FADE, fade, range); } - public static Module of(IWorld world, float fade) { - if (world instanceof RegionDelegate) { - WorldGenRegion region = ((RegionDelegate) world).getRegion(); - IChunk chunk = region.getChunk(region.getMainChunkX(), region.getMainChunkZ()); - return of(chunk, fade); - } - return Source.ONE; - } - - public static Module of(IChunk chunk, float fade) { - BiomeContainer container = chunk.getBiomes(); - if (container instanceof TerraContainer) { - ChunkReader reader = ((TerraContainer) container).getChunkReader(); + public static Module of(IWorld world, ChunkGenerator generator, float fade) { + ChunkReader reader = TerraChunkGenerator.getChunk(world, generator); + if (reader != null) { return new BiomeVariance(reader, fade); } return Source.ONE; diff --git a/src/main/java/com/terraforged/feature/decorator/poisson/PoissonConfig.java b/src/main/java/com/terraforged/feature/decorator/poisson/PoissonConfig.java index 44ba6fe..b4e0b0d 100644 --- a/src/main/java/com/terraforged/feature/decorator/poisson/PoissonConfig.java +++ b/src/main/java/com/terraforged/feature/decorator/poisson/PoissonConfig.java @@ -7,6 +7,7 @@ import com.terraforged.core.util.poisson.PoissonContext; import me.dags.noise.Module; import me.dags.noise.Source; import net.minecraft.world.IWorld; +import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.placement.IPlacementConfig; public class PoissonConfig implements IPlacementConfig { @@ -25,12 +26,12 @@ public class PoissonConfig implements IPlacementConfig { this.densityNoiseMax = densityNoiseMax; } - public void apply(IWorld world, PoissonContext context) { + public void apply(IWorld world, ChunkGenerator generator, PoissonContext context) { Module fade = Source.ONE; Module density = Source.ONE; if (biomeFade > 0.075F) { - fade = BiomeVariance.of(world, biomeFade); + fade = BiomeVariance.of(world, generator, biomeFade); } if (densityNoiseScale > 0) { diff --git a/src/main/java/com/terraforged/feature/decorator/poisson/PoissonDecorator.java b/src/main/java/com/terraforged/feature/decorator/poisson/PoissonDecorator.java index eadb599..2dafbcc 100644 --- a/src/main/java/com/terraforged/feature/decorator/poisson/PoissonDecorator.java +++ b/src/main/java/com/terraforged/feature/decorator/poisson/PoissonDecorator.java @@ -27,7 +27,7 @@ public abstract class PoissonDecorator extends Placement { int radius = Math.max(1, Math.min(30, config.radius)); Poisson poisson = getInstance(radius); PoissonVisitor visitor = new PoissonVisitor(this, feature, world, generator, random, pos); - config.apply(world, visitor); + config.apply(world, generator, visitor); int chunkX = pos.getX() >> 4; int chunkZ = pos.getZ() >> 4; poisson.visit(chunkX, chunkZ, visitor, visitor); diff --git a/src/main/java/com/terraforged/feature/feature/FreezeLayer.java b/src/main/java/com/terraforged/feature/feature/FreezeLayer.java new file mode 100644 index 0000000..17d9272 --- /dev/null +++ b/src/main/java/com/terraforged/feature/feature/FreezeLayer.java @@ -0,0 +1,72 @@ +package com.terraforged.feature.feature; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.SnowyDirtBlock; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.ChunkGenerator; +import net.minecraft.world.gen.GenerationSettings; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.NoFeatureConfig; + +import java.util.Random; + +public class FreezeLayer extends Feature { + + public static final FreezeLayer INSTANCE = new FreezeLayer(); + + public FreezeLayer() { + super(NoFeatureConfig::deserialize); + setRegistryName("terraforged", "freeze_top_layer"); + } + + @Override + public boolean place(IWorld world, ChunkGenerator generator, Random rand, BlockPos pos, NoFeatureConfig config) { + BlockPos.Mutable pos1 = new BlockPos.Mutable(); + BlockPos.Mutable pos2 = new BlockPos.Mutable(); + + for(int dx = 0; dx < 16; ++dx) { + for(int dz = 0; dz < 16; ++dz) { + int x = pos.getX() + dx; + int z = pos.getZ() + dz; + int y1 = world.getHeight(Heightmap.Type.MOTION_BLOCKING, x, z); + int y2 = world.getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); + pos1.setPos(x, y1, z); + pos2.setPos(pos1).move(Direction.DOWN, 1); + + Biome biome = world.getBiome(pos1); + boolean freezesHere = freeze(world, biome, pos1, pos2, false); + + if (y1 != y2) { + pos1.setPos(x, y2, z); + pos2.setPos(pos1).move(Direction.DOWN, 1); + freeze(world, biome, pos1, pos2, freezesHere); + } + } + } + + return true; + } + + private boolean freeze(IWorld world, Biome biome, BlockPos top, BlockPos below, boolean force) { + boolean hasFrozen = false; + if (biome.doesWaterFreeze(world, below, false)) { + world.setBlockState(below, Blocks.ICE.getDefaultState(), 2); + hasFrozen = true; + } + + if (force || biome.doesSnowGenerate(world, top)) { + hasFrozen = true; + world.setBlockState(top, Blocks.SNOW.getDefaultState(), 2); + BlockState blockstate = world.getBlockState(below); + if (blockstate.has(SnowyDirtBlock.SNOWY)) { + world.setBlockState(below, blockstate.with(SnowyDirtBlock.SNOWY, true), 2); + } + } + return hasFrozen; + } +}