- 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
This commit is contained in:
parent
94780baf98
commit
282817009e
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -176,13 +176,14 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
|
||||
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<GenerationSettings> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<ColumnDecorator> 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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<ChanceContext> 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<ChanceContext> pooled(IWorld world) {
|
||||
if (world instanceof RegionDelegate) {
|
||||
Levels levels = new Levels(world.getMaxHeight(), world.getSeaLevel());
|
||||
public static Resource<ChanceContext> 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<ChanceContext> pooled(IChunk chunk, Levels levels) {
|
||||
BiomeContainer container = chunk.getBiomes();
|
||||
if (container instanceof TerraContainer) {
|
||||
ChunkReader reader = ((TerraContainer) container).getChunkReader();
|
||||
Resource<ChanceContext> 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;
|
||||
|
@ -20,7 +20,7 @@ public class ContextSelectorFeature extends Feature<ContextSelectorConfig> {
|
||||
|
||||
@Override
|
||||
public boolean place(IWorld world, ChunkGenerator<? extends GenerationSettings> generator, Random random, BlockPos pos, ContextSelectorConfig config) {
|
||||
try (Resource<ChanceContext> item = ChanceContext.pooled(world)) {
|
||||
try (Resource<ChanceContext> item = ChanceContext.pooled(world, generator)) {
|
||||
if (item == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -27,7 +27,7 @@ public abstract class PoissonDecorator extends Placement<PoissonConfig> {
|
||||
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);
|
||||
|
@ -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<NoFeatureConfig> {
|
||||
|
||||
public static final FreezeLayer INSTANCE = new FreezeLayer();
|
||||
|
||||
public FreezeLayer() {
|
||||
super(NoFeatureConfig::deserialize);
|
||||
setRegistryName("terraforged", "freeze_top_layer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(IWorld world, ChunkGenerator<? extends GenerationSettings> 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user