mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-18 22:30:00 +00:00
WIP structure stage work
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package com.dfsek.terra.addons.generation.structure;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.generation.structure.config.BiomeStructuresTemplate;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureGenerationStageTemplate;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureLayerGridDescription;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureLayerGridDescription.Template;
|
||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
@@ -8,11 +13,17 @@ import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
import com.dfsek.terra.api.world.biome.Biome;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.provider.GenerationStageProvider;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class StructureGenerationAddon implements AddonInitializer {
|
||||
public static final TypeKey<Supplier<ObjectTemplate<GenerationStage>>> STAGE_TYPE_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@@ -24,20 +35,24 @@ public class StructureGenerationAddon implements AddonInitializer {
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> event.getPack()
|
||||
.getOrCreateRegistry(GenerationStageProvider.class)
|
||||
.register(addon.key("STRUCTURE"), pack -> new StructureGenerationStage(platform)))
|
||||
.failThrough();
|
||||
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigurationLoadEvent.class)
|
||||
.then(event -> {
|
||||
if(event.is(Biome.class)) {
|
||||
event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeStructuresTemplate()).get());
|
||||
}
|
||||
event.getPack().applyLoader(StructureLayerGridDescription.class, Template::new);
|
||||
|
||||
event.getPack()
|
||||
.getOrCreateRegistry(STAGE_TYPE_KEY)
|
||||
.register(addon.key("STRUCTURE"), StructureGenerationStageTemplate::new);
|
||||
})
|
||||
.failThrough();
|
||||
|
||||
// platform.getEventManager()
|
||||
// .getHandler(FunctionalEventHandler.class)
|
||||
// .register(addon, ConfigurationLoadEvent.class)
|
||||
// .then(event -> {
|
||||
// if(event.is(Biome.class)) {
|
||||
// event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeStructuresTemplate()).get());
|
||||
// }
|
||||
// })
|
||||
// .failThrough();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,35 @@
|
||||
package com.dfsek.terra.addons.generation.structure;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGrid;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.WorldChunk;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
|
||||
public class StructureGenerationStage implements GenerationStage {
|
||||
private final Platform platform;
|
||||
private final StructureLayerGrid lastLayer;
|
||||
|
||||
public StructureGenerationStage(Platform platform) { this.platform = platform; }
|
||||
public StructureGenerationStage(StructureLayerGrid lastLayer) {
|
||||
this.lastLayer = lastLayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(ProtoWorld world) {
|
||||
int chunkX = world.centerChunkX();
|
||||
int chunkZ = world.centerChunkZ();
|
||||
System.out.printf("Populating X%d Y%d%n", chunkX, chunkZ);
|
||||
long seed = world.getSeed();
|
||||
|
||||
Chunk writeChunk = new WorldChunk(world, chunkX, chunkZ);
|
||||
Chunk populatedChunk = lastLayer.getChunk(world, chunkX, chunkZ, seed);
|
||||
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
for (int y = world.getMinHeight(); y <= world.getMaxHeight(); ++y) {
|
||||
writeChunk.setBlock(x, y, z, populatedChunk.getBlock(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.dfsek.terra.addons.generation.structure.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.generation.structure.StructureGenerationStage;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGrid;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGridImpl;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.WorldStructureLayerGrid;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class StructureGenerationStageTemplate implements ObjectTemplate<GenerationStage> {
|
||||
@Value("layers")
|
||||
@Default
|
||||
List<StructureLayerGridDescription> layers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public GenerationStage get() {
|
||||
StructureLayerGrid layer = new WorldStructureLayerGrid();
|
||||
for (StructureLayerGridDescription description : layers) {
|
||||
layer = new StructureLayerGridImpl(layer, description.size(), description.padding(), description.structures(), description.distribution());
|
||||
}
|
||||
return new StructureGenerationStage(layer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.addons.generation.structure.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
|
||||
|
||||
public record StructureLayerGridDescription(int padding, int size, ProbabilityCollection<Structure> structures, NoiseSampler distribution) {
|
||||
public static class Template implements ObjectTemplate<StructureLayerGridDescription> {
|
||||
|
||||
@Value("padding")
|
||||
private int padding;
|
||||
|
||||
@Value("size")
|
||||
private int size;
|
||||
|
||||
@Value("structures.structures")
|
||||
private ProbabilityCollection<Structure> structures;
|
||||
|
||||
@Value("structures.distribution")
|
||||
private NoiseSampler distribution;
|
||||
|
||||
@Override
|
||||
public StructureLayerGridDescription get() {
|
||||
return new StructureLayerGridDescription(padding, size, structures, distribution);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class CopyOnWriteDelegatedChunk implements Chunk {
|
||||
|
||||
private Chunk delegate;
|
||||
private boolean writeOccurred;
|
||||
|
||||
public CopyOnWriteDelegatedChunk(Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
if (!writeOccurred) {
|
||||
writeOccurred = true;
|
||||
delegate = new OverlayChunk(delegate);
|
||||
}
|
||||
// TODO - Tiered caching
|
||||
// First sparse impl using hashmap, if number of set blocks exceeds certain threshold,
|
||||
// then swap delegate to vertically segmented chunk using BlockState[vertChunk][x][z][y]
|
||||
delegate.setBlock(x, y, z, data, physics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return delegate.getBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return delegate.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate.getHandle();
|
||||
}
|
||||
|
||||
public static class OverlayChunk implements Chunk {
|
||||
|
||||
private final Chunk delegate;
|
||||
private final int worldMinHeight;
|
||||
private final BlockState[][][] blocks;
|
||||
|
||||
public OverlayChunk(Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
ServerWorld world = delegate.getWorld();
|
||||
this.worldMinHeight = world.getMinHeight();
|
||||
this.blocks = new BlockState[16][16][world.getMaxHeight() - worldMinHeight];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
blocks[x][z][y - worldMinHeight] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
BlockState state = blocks[x][z][y - worldMinHeight];
|
||||
if (state == null) return delegate.getBlock(x, y, z);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return delegate.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate.getHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.Rotation;
|
||||
import com.dfsek.terra.api.util.cache.SeededVector2Key;
|
||||
import com.dfsek.terra.api.util.vector.Vector3Int;
|
||||
import com.dfsek.terra.api.world.WritableWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a section of the world that contains at most a single structure within the structure layer
|
||||
*/
|
||||
public class StructureCell {
|
||||
|
||||
private final Chunk[][] chunks;
|
||||
private final int size;
|
||||
private final int chunkOriginX;
|
||||
|
||||
private final int chunkOriginZ;
|
||||
|
||||
public StructureCell(StructureLayerGridImpl layer, ProtoWorld world, SeededVector2Key origin) {
|
||||
System.out.println("Generating structure cell");
|
||||
this.size = layer.getGridSizeChunks();
|
||||
|
||||
this.chunkOriginX = origin.x * size;
|
||||
this.chunkOriginZ = origin.z * size;
|
||||
|
||||
this.chunks = new Chunk[size][size];
|
||||
WorldView worldView = new WorldView(world);
|
||||
|
||||
for (int x = 0; x < size; ++x) {
|
||||
for (int z = 0; z < size; ++z) {
|
||||
int chunkX = origin.x + x;
|
||||
int chunkZ = origin.z + z;
|
||||
chunks[x][z] = new CopyOnWriteDelegatedChunk(layer.getPrevious().getChunk(world, chunkX, chunkZ, origin.seed));
|
||||
}
|
||||
}
|
||||
int minCoord = (chunkOriginX + layer.getPadding()) * 16;
|
||||
int maxCoord = (chunkOriginZ + layer.getGridSizeChunks() - layer.getPadding()) * 16;
|
||||
// TODO - Make these random within the range
|
||||
int structureX = (minCoord + maxCoord) / 2;
|
||||
int structureZ = (minCoord + maxCoord) / 2;
|
||||
int structureY = (world.getMinHeight() + world.getMaxHeight()) / 2;
|
||||
Vector3Int structureOrigin = Vector3Int.of(structureX, structureY, structureZ);
|
||||
|
||||
Structure structure = layer.getStructures().get(layer.getDistribution(), structureOrigin, origin.seed);
|
||||
|
||||
structure.generate(structureOrigin, worldView, null /* TODO */, Rotation.NONE /* TODO */);
|
||||
}
|
||||
|
||||
public Chunk getChunk(int chunkX, int chunkZ) {
|
||||
return getChunkLocal(chunkX - chunkOriginX, chunkZ - chunkOriginZ);
|
||||
}
|
||||
|
||||
private Chunk getChunkLocal(int ix, int iz) {
|
||||
if (ix < 0 || ix >= size || iz < 0 || iz >= size)
|
||||
throw new IndexOutOfBoundsException("Attempted to retrieve chunk outside of structure cell bounds");
|
||||
return chunks[ix][iz];
|
||||
}
|
||||
|
||||
class WorldView implements WritableWorld {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WorldView.class);
|
||||
|
||||
private final ProtoWorld worldDelegate;
|
||||
|
||||
private WorldView(ProtoWorld world) {
|
||||
this.worldDelegate = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
Chunk chunk = getChunkSafe(chunkX, chunkZ);
|
||||
int xInChunk = x - chunkX << 4;
|
||||
int zInChunk = z - chunkZ << 4;
|
||||
chunk.setBlock(xInChunk, y, zInChunk, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return worldDelegate.spawnEntity(x, y, z, entityType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
Chunk chunk = getChunkSafe(chunkX, chunkZ);
|
||||
int xInChunk = x - chunkX << 4;
|
||||
int zInChunk = z - chunkZ << 4;
|
||||
return chunk.getBlock(xInChunk, y, zInChunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return worldDelegate.getBlockEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return worldDelegate.getGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return worldDelegate.getBiomeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return worldDelegate.getPack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return worldDelegate.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return worldDelegate.getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return worldDelegate.getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return worldDelegate.getHandle();
|
||||
}
|
||||
|
||||
private Chunk getChunkSafe(int chunkX, int chunkZ) {
|
||||
try {
|
||||
return getChunk(chunkX, chunkZ);
|
||||
} catch(IndexOutOfBoundsException e) {
|
||||
logger.warn("Chunk accessed outside permissible structure boundaries, this may cause unexpected behaviour");
|
||||
return new WorldChunk(worldDelegate, chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
|
||||
public interface StructureLayerGrid {
|
||||
Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.cache.SeededVector2Key;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
|
||||
public class StructureLayerGridImpl implements StructureLayerGrid {
|
||||
|
||||
private final StructureLayerGrid previous;
|
||||
private final Cache<SeededVector2Key, StructureCell> structureCells;
|
||||
|
||||
private final int padding;
|
||||
private final int cellSize;
|
||||
|
||||
protected ProbabilityCollection<Structure> getStructures() {
|
||||
return structures;
|
||||
}
|
||||
|
||||
protected NoiseSampler getDistribution() {
|
||||
return distribution;
|
||||
}
|
||||
|
||||
private final ProbabilityCollection<Structure> structures;
|
||||
private final NoiseSampler distribution;
|
||||
|
||||
public StructureLayerGridImpl(StructureLayerGrid previous, int size, int padding, ProbabilityCollection<Structure> structures,
|
||||
NoiseSampler distribution) {
|
||||
this.previous = previous;
|
||||
this.padding = padding;
|
||||
this.structures = structures;
|
||||
this.distribution = distribution;
|
||||
this.cellSize = 1 + (size + padding) * 2;
|
||||
this.structureCells = Caffeine.newBuilder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed) {
|
||||
int cellX = Math.floorMod(chunkX, cellSize);
|
||||
int cellZ = Math.floorMod(chunkZ, cellSize);
|
||||
SeededVector2Key lookupPos = new SeededVector2Key(cellX, cellZ, seed);
|
||||
StructureCell cell = structureCells.get(lookupPos, pos -> new StructureCell(this, world, pos));
|
||||
return cell.getChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
protected int getGridSizeChunks() {
|
||||
return cellSize;
|
||||
}
|
||||
|
||||
protected StructureLayerGrid getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected int getPadding() {
|
||||
return padding;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.WritableWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* Temp class that just delegates chunk operations to the world on a block-by-block basis
|
||||
*/
|
||||
public class WorldChunk implements Chunk {
|
||||
|
||||
private final WritableWorld world;
|
||||
private final int x;
|
||||
private final int z;
|
||||
|
||||
public WorldChunk(WritableWorld world, int x, int z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
world.setBlockState(x, y, z, data, physics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return world.getBlockState(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
|
||||
public class WorldStructureLayerGrid implements StructureLayerGrid {
|
||||
@Override
|
||||
public Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed) {
|
||||
return new WorldChunk(world, chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user