- 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.context.ContextSelectorFeature;
|
||||||
import com.terraforged.feature.decorator.poisson.PoissonAtSurface;
|
import com.terraforged.feature.decorator.poisson.PoissonAtSurface;
|
||||||
import com.terraforged.feature.feature.DiskFeature;
|
import com.terraforged.feature.feature.DiskFeature;
|
||||||
|
import com.terraforged.feature.feature.FreezeLayer;
|
||||||
import com.terraforged.fm.template.TemplateManager;
|
import com.terraforged.fm.template.TemplateManager;
|
||||||
import com.terraforged.settings.SettingsHelper;
|
import com.terraforged.settings.SettingsHelper;
|
||||||
import com.terraforged.util.DataPackFinder;
|
import com.terraforged.util.DataPackFinder;
|
||||||
@ -83,6 +84,7 @@ public class TerraForgedMod {
|
|||||||
Log.info("Registering features");
|
Log.info("Registering features");
|
||||||
TemplateManager.register(event);
|
TemplateManager.register(event);
|
||||||
event.getRegistry().register(DiskFeature.INSTANCE);
|
event.getRegistry().register(DiskFeature.INSTANCE);
|
||||||
|
event.getRegistry().register(FreezeLayer.INSTANCE);
|
||||||
event.getRegistry().register(ContextSelectorFeature.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 BeachModifier(biomes, context));
|
||||||
modifiers.add(new DesertColorModifier(desertBiomes));
|
modifiers.add(new DesertColorModifier(desertBiomes));
|
||||||
modifiers.add(new SandBiomeModifier(context));
|
modifiers.add(new SandBiomeModifier(context));
|
||||||
|
modifiers.add(new MushroomModifier());
|
||||||
Collections.sort(modifiers);
|
Collections.sort(modifiers);
|
||||||
this.biomeModifiers = 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,7 +176,7 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
|
|||||||
public final int func_222529_a(int x, int z, Heightmap.Type type) {
|
public final int func_222529_a(int x, int z, Heightmap.Type type) {
|
||||||
int chunkX = Size.blockToChunk(x);
|
int chunkX = Size.blockToChunk(x);
|
||||||
int chunkZ = Size.blockToChunk(z);
|
int chunkZ = Size.blockToChunk(z);
|
||||||
ChunkReader chunk = getChunkReader(chunkX, chunkZ);
|
try (ChunkReader chunk = getChunkReader(chunkX, chunkZ)) {
|
||||||
Cell cell = chunk.getCell(x, z);
|
Cell cell = chunk.getCell(x, z);
|
||||||
int level = context.levels.scale(cell.value) + 1;
|
int level = context.levels.scale(cell.value) + 1;
|
||||||
if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) {
|
if (type == Heightmap.Type.OCEAN_FLOOR || type == Heightmap.Type.OCEAN_FLOOR_WG) {
|
||||||
@ -184,6 +184,7 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
|
|||||||
}
|
}
|
||||||
return Math.max(getSeaLevel(), level);
|
return Math.max(getSeaLevel(), level);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeProvider getBiomeProvider() {
|
public BiomeProvider getBiomeProvider() {
|
||||||
@ -260,4 +261,20 @@ public class TerraChunkGenerator extends ChunkGenerator<GenerationSettings> {
|
|||||||
public final ChunkReader getChunkReader(int chunkX, int chunkZ) {
|
public final ChunkReader getChunkReader(int chunkX, int chunkZ) {
|
||||||
return regionCache.getChunk(chunkX, 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.chunk.column.post.SnowEroder;
|
||||||
import com.terraforged.feature.BlockDataManager;
|
import com.terraforged.feature.BlockDataManager;
|
||||||
import com.terraforged.feature.Matchers;
|
import com.terraforged.feature.Matchers;
|
||||||
|
import com.terraforged.feature.feature.FreezeLayer;
|
||||||
import com.terraforged.fm.FeatureManager;
|
import com.terraforged.fm.FeatureManager;
|
||||||
import com.terraforged.fm.data.DataManager;
|
import com.terraforged.fm.data.DataManager;
|
||||||
import com.terraforged.fm.matcher.biome.BiomeMatcher;
|
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.FeaturePredicate;
|
||||||
import com.terraforged.fm.predicate.MinHeight;
|
import com.terraforged.fm.predicate.MinHeight;
|
||||||
import com.terraforged.fm.structure.StructureManager;
|
import com.terraforged.fm.structure.StructureManager;
|
||||||
|
import com.terraforged.fm.transformer.FeatureTransformer;
|
||||||
import com.terraforged.material.geology.GeoManager;
|
import com.terraforged.material.geology.GeoManager;
|
||||||
import com.terraforged.util.setup.SetupHooks;
|
import com.terraforged.util.setup.SetupHooks;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
@ -90,6 +92,13 @@ public class TerraSetupFactory {
|
|||||||
if (context.terraSettings.features.customBiomeFeatures) {
|
if (context.terraSettings.features.customBiomeFeatures) {
|
||||||
// remove default trees from river biomes since forests can go up to the edge of rivers
|
// 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);
|
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
|
// block ugly features
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.terraforged.chunk.generator;
|
package com.terraforged.chunk.generator;
|
||||||
|
|
||||||
|
import com.terraforged.biome.provider.BiomeProvider;
|
||||||
import com.terraforged.chunk.TerraChunkGenerator;
|
import com.terraforged.chunk.TerraChunkGenerator;
|
||||||
import com.terraforged.chunk.util.TerraContainer;
|
import com.terraforged.chunk.util.TerraContainer;
|
||||||
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import com.terraforged.world.terrain.decorator.Decorator;
|
import com.terraforged.world.terrain.decorator.Decorator;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.util.math.ChunkPos;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
@ -10,23 +12,27 @@ import net.minecraft.world.chunk.IChunk;
|
|||||||
public class BiomeGenerator {
|
public class BiomeGenerator {
|
||||||
|
|
||||||
private final TerraChunkGenerator generator;
|
private final TerraChunkGenerator generator;
|
||||||
|
private final BiomeProvider biomeProvider;
|
||||||
|
|
||||||
public BiomeGenerator(TerraChunkGenerator generator) {
|
public BiomeGenerator(TerraChunkGenerator generator) {
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
|
this.biomeProvider = generator.getBiomeProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateBiomes(IChunk chunk) {
|
public void generateBiomes(IChunk chunk) {
|
||||||
ChunkPos pos = chunk.getPos();
|
ChunkPos pos = chunk.getPos();
|
||||||
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
|
try (ChunkReader reader = generator.getChunkReader(pos.x, pos.z)) {
|
||||||
|
TerraContainer container = TerraContainer.create(reader, generator.getBiomeProvider());
|
||||||
// apply chunk-local heightmap modifications
|
// apply chunk-local heightmap modifications
|
||||||
preProcess(pos, container);
|
preProcess(reader, container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preProcess(ChunkPos pos, TerraContainer container) {
|
private void preProcess(ChunkReader reader, TerraContainer biomes) {
|
||||||
container.getChunkReader().iterate((cell, dx, dz) -> {
|
reader.iterate((cell, dx, dz) -> {
|
||||||
Biome biome = container.getBiome(dx, dz);
|
Biome biome = biomes.getBiome(dx, dz);
|
||||||
for (Decorator decorator : generator.getBiomeProvider().getDecorators(biome)) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,11 @@ public class FeatureGenerator {
|
|||||||
int chunkX = region.getMainChunkX();
|
int chunkX = region.getMainChunkX();
|
||||||
int chunkZ = region.getMainChunkZ();
|
int chunkZ = region.getMainChunkZ();
|
||||||
IChunk chunk = region.getChunk(chunkX, chunkZ);
|
IChunk chunk = region.getChunk(chunkX, chunkZ);
|
||||||
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
|
|
||||||
|
|
||||||
ChunkReader chunkReader = generator.getChunkReader(chunkX, chunkZ);
|
ChunkReader reader = generator.getChunkReader(chunkX, chunkZ);
|
||||||
Biome biome = container.getFeatureBiome(chunkReader);
|
TerraContainer container = TerraContainer.getOrCreate(chunk, reader, generator.getBiomeProvider());
|
||||||
|
|
||||||
|
Biome biome = container.getFeatureBiome(reader);
|
||||||
DecoratorContext context = generator.getContext().decorator(chunk);
|
DecoratorContext context = generator.getContext().decorator(chunk);
|
||||||
|
|
||||||
IWorld regionFix = new RegionFix(region, generator);
|
IWorld regionFix = new RegionFix(region, generator);
|
||||||
@ -42,15 +43,21 @@ public class FeatureGenerator {
|
|||||||
generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos);
|
generator.getFeatureManager().decorate(generator, regionFix, chunk, biome, pos);
|
||||||
|
|
||||||
// run post processes on chunk
|
// 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()));
|
((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();
|
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 px = ctx.blockX + dx;
|
||||||
int pz = ctx.blockZ + dz;
|
int pz = ctx.blockZ + dz;
|
||||||
int py = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, 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.TerraChunkGenerator;
|
||||||
import com.terraforged.chunk.util.FastChunk;
|
import com.terraforged.chunk.util.FastChunk;
|
||||||
import com.terraforged.chunk.util.TerraContainer;
|
import com.terraforged.chunk.util.TerraContainer;
|
||||||
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import net.minecraft.util.SharedSeedRandom;
|
import net.minecraft.util.SharedSeedRandom;
|
||||||
import net.minecraft.world.chunk.IChunk;
|
import net.minecraft.world.chunk.IChunk;
|
||||||
import net.minecraft.world.gen.Heightmap;
|
import net.minecraft.world.gen.Heightmap;
|
||||||
@ -24,11 +25,12 @@ public class SurfaceGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void generateSurface(WorldGenRegion world, IChunk chunk) {
|
public final void generateSurface(WorldGenRegion world, IChunk chunk) {
|
||||||
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
|
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));
|
ChunkSurfaceBuffer buffer = new ChunkSurfaceBuffer(FastChunk.wrap(chunk));
|
||||||
|
|
||||||
try (SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings())) {
|
try (SurfaceContext context = generator.getContext().surface(buffer, generator.getSettings())) {
|
||||||
container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> {
|
reader.iterate(context, (cell, dx, dz, ctx) -> {
|
||||||
int px = ctx.blockX + dx;
|
int px = ctx.blockX + dx;
|
||||||
int pz = ctx.blockZ + dz;
|
int pz = ctx.blockZ + dz;
|
||||||
int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz);
|
int top = ctx.chunk.getTopBlockY(Heightmap.Type.WORLD_SURFACE_WG, dx, dz);
|
||||||
@ -50,6 +52,7 @@ public class SurfaceGenerator {
|
|||||||
FastChunk.updateWGHeightmaps(chunk, context.pos);
|
FastChunk.updateWGHeightmaps(chunk, context.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private double getSurfaceNoise(int x, int z) {
|
private double getSurfaceNoise(int x, int z) {
|
||||||
double scale = 0.0625D;
|
double scale = 0.0625D;
|
||||||
|
@ -5,6 +5,7 @@ import com.terraforged.chunk.TerraChunkGenerator;
|
|||||||
import com.terraforged.chunk.column.ChunkPopulator;
|
import com.terraforged.chunk.column.ChunkPopulator;
|
||||||
import com.terraforged.chunk.util.FastChunk;
|
import com.terraforged.chunk.util.FastChunk;
|
||||||
import com.terraforged.chunk.util.TerraContainer;
|
import com.terraforged.chunk.util.TerraContainer;
|
||||||
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import com.terraforged.feature.TerrainHelper;
|
import com.terraforged.feature.TerrainHelper;
|
||||||
import com.terraforged.world.climate.Climate;
|
import com.terraforged.world.climate.Climate;
|
||||||
import com.terraforged.world.heightmap.Levels;
|
import com.terraforged.world.heightmap.Levels;
|
||||||
@ -29,9 +30,10 @@ public class TerrainGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void generateTerrain(IWorld world, IChunk chunk) {
|
public final void generateTerrain(IWorld world, IChunk chunk) {
|
||||||
TerraContainer container = TerraContainer.getOrCreate(chunk, generator);
|
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)) {
|
try (DecoratorContext context = new DecoratorContext(FastChunk.wrap(chunk), levels, terrain, climate)) {
|
||||||
container.getChunkReader().iterate(context, (cell, dx, dz, ctx) -> {
|
reader.iterate(context, (cell, dx, dz, ctx) -> {
|
||||||
int px = ctx.blockX + dx;
|
int px = ctx.blockX + dx;
|
||||||
int pz = ctx.blockZ + dz;
|
int pz = ctx.blockZ + dz;
|
||||||
int py = ctx.levels.scale(cell.value);
|
int py = ctx.levels.scale(cell.value);
|
||||||
@ -42,4 +44,5 @@ public class TerrainGenerator {
|
|||||||
terrainHelper.flatten(world, chunk);
|
terrainHelper.flatten(world, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package com.terraforged.chunk.util;
|
package com.terraforged.chunk.util;
|
||||||
|
|
||||||
import com.terraforged.api.biome.BiomeVariant;
|
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.cell.Cell;
|
||||||
import com.terraforged.core.region.chunk.ChunkReader;
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import com.terraforged.core.util.PosIterator;
|
import com.terraforged.core.util.PosIterator;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
import net.minecraft.world.biome.BiomeContainer;
|
import net.minecraft.world.biome.BiomeContainer;
|
||||||
@ -23,17 +22,11 @@ public class TerraContainer extends BiomeContainer {
|
|||||||
|
|
||||||
private final Biome[] biomes;
|
private final Biome[] biomes;
|
||||||
private final Biome[] surface;
|
private final Biome[] surface;
|
||||||
private final ChunkReader chunkReader;
|
|
||||||
|
|
||||||
public TerraContainer(Biome[] biomes, Biome[] surface, ChunkReader chunkReader) {
|
public TerraContainer(Biome[] biomes, Biome[] surface) {
|
||||||
super(biomes);
|
super(biomes);
|
||||||
this.biomes = biomes;
|
this.biomes = biomes;
|
||||||
this.surface = surface;
|
this.surface = surface;
|
||||||
this.chunkReader = chunkReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChunkReader getChunkReader() {
|
|
||||||
return chunkReader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Biome getBiome(int x, int z) {
|
public Biome getBiome(int x, int z) {
|
||||||
@ -68,28 +61,26 @@ public class TerraContainer extends BiomeContainer {
|
|||||||
return new BiomeContainer(biomes);
|
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) {
|
if (chunk.getBiomes() instanceof TerraContainer) {
|
||||||
return (TerraContainer) chunk.getBiomes();
|
return (TerraContainer) chunk.getBiomes();
|
||||||
} else {
|
} else {
|
||||||
TerraContainer container = TerraContainer.create(generator, chunk.getPos());
|
TerraContainer container = TerraContainer.create(reader, biomeProvider);
|
||||||
((ChunkPrimer) chunk).func_225548_a_(container);
|
((ChunkPrimer) chunk).func_225548_a_(container);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TerraContainer create(TerraChunkGenerator generator, ChunkPos pos) {
|
public static TerraContainer create(ChunkReader chunkReader, BiomeProvider biomeProvider) {
|
||||||
ChunkReader reader = generator.getChunkReader(pos.x, pos.z);
|
|
||||||
|
|
||||||
Biome[] biomes2D = new Biome[BIOMES_2D_SIZE];
|
Biome[] biomes2D = new Biome[BIOMES_2D_SIZE];
|
||||||
Biome[] biomes3D = new Biome[BIOMES_3D_SIZE];
|
Biome[] biomes3D = new Biome[BIOMES_3D_SIZE];
|
||||||
PosIterator iterator = PosIterator.area(0, 0, 16, 16);
|
PosIterator iterator = PosIterator.area(0, 0, 16, 16);
|
||||||
while (iterator.next()) {
|
while (iterator.next()) {
|
||||||
int dx = iterator.x();
|
int dx = iterator.x();
|
||||||
int dz = iterator.z();
|
int dz = iterator.z();
|
||||||
int x = pos.getXStart() + dx;
|
int x = chunkReader.getBlockX() + dx;
|
||||||
int z = pos.getZStart() + dz;
|
int z = chunkReader.getBlockZ() + dz;
|
||||||
Biome biome = generator.getBiomeProvider().getBiome(reader.getCell(dx, dz), x, z);
|
Biome biome = biomeProvider.getBiome(chunkReader.getCell(dx, dz), x, z);
|
||||||
biomes2D[indexOf(dx, dz)] = biome;
|
biomes2D[indexOf(dx, dz)] = biome;
|
||||||
if ((dx & 3) == 0 && (dz & 3) == 0) {
|
if ((dx & 3) == 0 && (dz & 3) == 0) {
|
||||||
for (int dy = 0; dy < 64; dy++) {
|
for (int dy = 0; dy < 64; dy++) {
|
||||||
@ -97,8 +88,7 @@ public class TerraContainer extends BiomeContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return new TerraContainer(biomes3D, biomes2D);
|
||||||
return new TerraContainer(biomes3D, biomes2D, reader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int indexOf(int x, int z) {
|
private static int indexOf(int x, int z) {
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
package com.terraforged.feature.context;
|
package com.terraforged.feature.context;
|
||||||
|
|
||||||
|
import com.terraforged.chunk.TerraChunkGenerator;
|
||||||
import com.terraforged.chunk.fix.RegionDelegate;
|
import com.terraforged.chunk.fix.RegionDelegate;
|
||||||
import com.terraforged.chunk.util.TerraContainer;
|
|
||||||
import com.terraforged.core.cell.Cell;
|
import com.terraforged.core.cell.Cell;
|
||||||
import com.terraforged.core.concurrent.Resource;
|
import com.terraforged.core.concurrent.Resource;
|
||||||
|
import com.terraforged.core.concurrent.cache.SafeCloseable;
|
||||||
import com.terraforged.core.concurrent.pool.ObjectPool;
|
import com.terraforged.core.concurrent.pool.ObjectPool;
|
||||||
import com.terraforged.core.region.chunk.ChunkReader;
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import com.terraforged.world.heightmap.Levels;
|
import com.terraforged.world.heightmap.Levels;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.biome.BiomeContainer;
|
|
||||||
import net.minecraft.world.chunk.IChunk;
|
import net.minecraft.world.chunk.IChunk;
|
||||||
|
import net.minecraft.world.gen.ChunkGenerator;
|
||||||
import net.minecraft.world.gen.WorldGenRegion;
|
import net.minecraft.world.gen.WorldGenRegion;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class ChanceContext {
|
public class ChanceContext implements SafeCloseable {
|
||||||
|
|
||||||
private static final ObjectPool<ChanceContext> pool = new ObjectPool<>(10, ChanceContext::new);
|
private static final ObjectPool<ChanceContext> pool = new ObjectPool<>(10, ChanceContext::new);
|
||||||
|
|
||||||
@ -28,6 +29,14 @@ public class ChanceContext {
|
|||||||
private float total = 0F;
|
private float total = 0F;
|
||||||
private float[] buffer;
|
private float[] buffer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (reader != null) {
|
||||||
|
reader.close();
|
||||||
|
reader = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setPos(BlockPos pos) {
|
void setPos(BlockPos pos) {
|
||||||
cell = reader.getCell(pos.getX(), pos.getZ());
|
cell = reader.getCell(pos.getX(), pos.getZ());
|
||||||
}
|
}
|
||||||
@ -61,25 +70,16 @@ public class ChanceContext {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Resource<ChanceContext> pooled(IWorld world) {
|
public static Resource<ChanceContext> pooled(IWorld world, ChunkGenerator<?> generator) {
|
||||||
if (world instanceof RegionDelegate) {
|
if (generator instanceof TerraChunkGenerator && world instanceof RegionDelegate) {
|
||||||
Levels levels = new Levels(world.getMaxHeight(), world.getSeaLevel());
|
TerraChunkGenerator terraGenerator = (TerraChunkGenerator) generator;
|
||||||
|
Levels levels = terraGenerator.getContext().levels;
|
||||||
WorldGenRegion region = ((RegionDelegate) world).getRegion();
|
WorldGenRegion region = ((RegionDelegate) world).getRegion();
|
||||||
IChunk chunk = region.getChunk(region.getMainChunkX(), region.getMainChunkZ());
|
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();
|
Resource<ChanceContext> item = pool.get();
|
||||||
ChanceContext context = item.get();
|
item.get().chunk = chunk;
|
||||||
context.chunk = chunk;
|
item.get().levels = levels;
|
||||||
context.levels = levels;
|
item.get().reader = terraGenerator.getChunkReader(chunk.getPos().x, chunk.getPos().z);
|
||||||
context.reader = reader;
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -20,7 +20,7 @@ public class ContextSelectorFeature extends Feature<ContextSelectorConfig> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean place(IWorld world, ChunkGenerator<? extends GenerationSettings> generator, Random random, BlockPos pos, ContextSelectorConfig config) {
|
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) {
|
if (item == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
package com.terraforged.feature.decorator.poisson;
|
package com.terraforged.feature.decorator.poisson;
|
||||||
|
|
||||||
import com.terraforged.chunk.fix.RegionDelegate;
|
import com.terraforged.chunk.TerraChunkGenerator;
|
||||||
import com.terraforged.chunk.util.TerraContainer;
|
|
||||||
import com.terraforged.core.cell.Cell;
|
import com.terraforged.core.cell.Cell;
|
||||||
import com.terraforged.core.region.chunk.ChunkReader;
|
import com.terraforged.core.region.chunk.ChunkReader;
|
||||||
import me.dags.noise.Module;
|
import me.dags.noise.Module;
|
||||||
import me.dags.noise.Source;
|
import me.dags.noise.Source;
|
||||||
import me.dags.noise.util.NoiseUtil;
|
import me.dags.noise.util.NoiseUtil;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.biome.BiomeContainer;
|
import net.minecraft.world.gen.ChunkGenerator;
|
||||||
import net.minecraft.world.chunk.IChunk;
|
|
||||||
import net.minecraft.world.gen.WorldGenRegion;
|
|
||||||
|
|
||||||
public class BiomeVariance implements Module {
|
public class BiomeVariance implements Module {
|
||||||
|
|
||||||
@ -32,19 +29,9 @@ public class BiomeVariance implements Module {
|
|||||||
return NoiseUtil.map(1 - cell.biomeEdge, MIN_FADE, fade, range);
|
return NoiseUtil.map(1 - cell.biomeEdge, MIN_FADE, fade, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Module of(IWorld world, float fade) {
|
public static Module of(IWorld world, ChunkGenerator<?> generator, float fade) {
|
||||||
if (world instanceof RegionDelegate) {
|
ChunkReader reader = TerraChunkGenerator.getChunk(world, generator);
|
||||||
WorldGenRegion region = ((RegionDelegate) world).getRegion();
|
if (reader != null) {
|
||||||
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();
|
|
||||||
return new BiomeVariance(reader, fade);
|
return new BiomeVariance(reader, fade);
|
||||||
}
|
}
|
||||||
return Source.ONE;
|
return Source.ONE;
|
||||||
|
@ -7,6 +7,7 @@ import com.terraforged.core.util.poisson.PoissonContext;
|
|||||||
import me.dags.noise.Module;
|
import me.dags.noise.Module;
|
||||||
import me.dags.noise.Source;
|
import me.dags.noise.Source;
|
||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
|
import net.minecraft.world.gen.ChunkGenerator;
|
||||||
import net.minecraft.world.gen.placement.IPlacementConfig;
|
import net.minecraft.world.gen.placement.IPlacementConfig;
|
||||||
|
|
||||||
public class PoissonConfig implements IPlacementConfig {
|
public class PoissonConfig implements IPlacementConfig {
|
||||||
@ -25,12 +26,12 @@ public class PoissonConfig implements IPlacementConfig {
|
|||||||
this.densityNoiseMax = densityNoiseMax;
|
this.densityNoiseMax = densityNoiseMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply(IWorld world, PoissonContext context) {
|
public void apply(IWorld world, ChunkGenerator<?> generator, PoissonContext context) {
|
||||||
Module fade = Source.ONE;
|
Module fade = Source.ONE;
|
||||||
Module density = Source.ONE;
|
Module density = Source.ONE;
|
||||||
|
|
||||||
if (biomeFade > 0.075F) {
|
if (biomeFade > 0.075F) {
|
||||||
fade = BiomeVariance.of(world, biomeFade);
|
fade = BiomeVariance.of(world, generator, biomeFade);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (densityNoiseScale > 0) {
|
if (densityNoiseScale > 0) {
|
||||||
|
@ -27,7 +27,7 @@ public abstract class PoissonDecorator extends Placement<PoissonConfig> {
|
|||||||
int radius = Math.max(1, Math.min(30, config.radius));
|
int radius = Math.max(1, Math.min(30, config.radius));
|
||||||
Poisson poisson = getInstance(radius);
|
Poisson poisson = getInstance(radius);
|
||||||
PoissonVisitor visitor = new PoissonVisitor(this, feature, world, generator, random, pos);
|
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 chunkX = pos.getX() >> 4;
|
||||||
int chunkZ = pos.getZ() >> 4;
|
int chunkZ = pos.getZ() >> 4;
|
||||||
poisson.visit(chunkX, chunkZ, visitor, visitor);
|
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