mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-06-19 07:11:14 +00:00
feat: cache generated chunks
This commit is in preparation of multi-layered worldgen with minestom
This commit is contained in:
@@ -6,10 +6,7 @@ val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample"
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
shadedApi(project(":common:implementation:base"))
|
shadedApi(project(":common:implementation:base"))
|
||||||
|
shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine)
|
||||||
//shadedApi("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
|
|
||||||
//shadedApi("com.github.Querz", "NBT", Versions.CLI.nbt)
|
|
||||||
|
|
||||||
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||||
|
|
||||||
implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom)
|
implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom)
|
||||||
|
|||||||
+5
-2
@@ -7,7 +7,6 @@ import com.dfsek.terra.api.block.state.properties.Property;
|
|||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@@ -15,7 +14,11 @@ public class MinestomBlockState implements BlockState {
|
|||||||
private final Block block;
|
private final Block block;
|
||||||
|
|
||||||
public MinestomBlockState(Block block) {
|
public MinestomBlockState(Block block) {
|
||||||
this.block = block;
|
if (block == null) {
|
||||||
|
this.block = Block.AIR;
|
||||||
|
} else {
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinestomBlockState(String data) {
|
public MinestomBlockState(String data) {
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.dfsek.terra.minestom.chunk;
|
||||||
|
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.block.state.BlockState;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
||||||
|
import com.dfsek.terra.minestom.block.MinestomBlockState;
|
||||||
|
import net.minestom.server.instance.block.Block;
|
||||||
|
import net.minestom.server.instance.generator.UnitModifier;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
|
||||||
|
public class CachedChunk implements ProtoChunk {
|
||||||
|
private final int minHeight;
|
||||||
|
private final int maxHeight;
|
||||||
|
private final Block[][][] blocks;
|
||||||
|
|
||||||
|
public CachedChunk(int minHeight, int maxHeight) {
|
||||||
|
this.minHeight = minHeight;
|
||||||
|
this.maxHeight = maxHeight;
|
||||||
|
this.blocks = new Block[16][maxHeight - minHeight + 1][16];
|
||||||
|
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
for (int y = 0; y < maxHeight - minHeight + 1; y++) {
|
||||||
|
blocks[x][y][z] = Block.AIR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeRelative(UnitModifier modifier) {
|
||||||
|
modifier.setAllRelative((x, y, z) -> blocks[x][y][z]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
||||||
|
Block block = (Block) blockState.getHandle();
|
||||||
|
if(block == null) return;
|
||||||
|
blocks[x][y - minHeight][z] = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||||
|
return new MinestomBlockState(blocks[x][y - minHeight][z]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getHandle() {
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package com.dfsek.terra.minestom.chunk;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||||
|
|
||||||
|
import com.dfsek.terra.api.world.ServerWorld;
|
||||||
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import net.minestom.server.world.DimensionType;
|
||||||
|
|
||||||
|
|
||||||
|
public class GeneratedChunkCache {
|
||||||
|
private final LoadingCache<Pair<Integer, Integer>, CachedChunk> cache;
|
||||||
|
private final DimensionType dimensionType;
|
||||||
|
private final ChunkGenerator generator;
|
||||||
|
private final ServerWorld world;
|
||||||
|
private final BiomeProvider biomeProvider;
|
||||||
|
|
||||||
|
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world) {
|
||||||
|
this.dimensionType = dimensionType;
|
||||||
|
this.generator = generator;
|
||||||
|
this.world = world;
|
||||||
|
this.biomeProvider = world.getBiomeProvider();
|
||||||
|
this.cache = Caffeine.newBuilder()
|
||||||
|
.maximumSize(32)
|
||||||
|
.build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachedChunk generateChunk(int x, int z) {
|
||||||
|
CachedChunk chunk = new CachedChunk(dimensionType.minY(), dimensionType.maxY());
|
||||||
|
generator.generateChunkData(
|
||||||
|
chunk,
|
||||||
|
world,
|
||||||
|
biomeProvider,
|
||||||
|
x, z
|
||||||
|
);
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedChunk at(int x, int y) {
|
||||||
|
return cache.get(Pair.of(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
package com.dfsek.terra.minestom.chunk;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
|
|
||||||
|
|
||||||
import net.minestom.server.instance.block.Block;
|
|
||||||
import net.minestom.server.instance.generator.UnitModifier;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
|
||||||
public class MinestomProtoChunk implements ProtoChunk {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MinestomProtoChunk.class);
|
|
||||||
private final int minHeight;
|
|
||||||
private final int maxHeight;
|
|
||||||
private final UnitModifier modifier;
|
|
||||||
|
|
||||||
public MinestomProtoChunk(int maxHeight, int minHeight, @NotNull UnitModifier modifier) {
|
|
||||||
this.minHeight = minHeight;
|
|
||||||
this.maxHeight = maxHeight;
|
|
||||||
this.modifier = modifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxHeight() {
|
|
||||||
return maxHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
|
|
||||||
try {
|
|
||||||
modifier.setRelative(x, y - minHeight, z, (Block) blockState.getHandle());
|
|
||||||
} catch(Exception e) {
|
|
||||||
log.error("Failed setting Block at {} {} {} to {} (min={}, max={})", x, y, z, blockState.getHandle(), minHeight, maxHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
|
||||||
System.out.println("Block access at " + x + ", " + y + ", " + z + " is not supported.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getHandle() {
|
|
||||||
return modifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+9
-11
@@ -2,7 +2,8 @@ package com.dfsek.terra.minestom.world;
|
|||||||
|
|
||||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||||
|
|
||||||
import com.dfsek.terra.minestom.chunk.MinestomProtoChunk;
|
import com.dfsek.terra.minestom.chunk.CachedChunk;
|
||||||
|
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
|
||||||
|
|
||||||
import net.minestom.server.coordinate.Point;
|
import net.minestom.server.coordinate.Point;
|
||||||
import net.minestom.server.instance.generator.GenerationUnit;
|
import net.minestom.server.instance.generator.GenerationUnit;
|
||||||
@@ -11,12 +12,12 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
|
|
||||||
public class MinestomChunkGeneratorWrapper implements Generator {
|
public class MinestomChunkGeneratorWrapper implements Generator {
|
||||||
|
private final GeneratedChunkCache cache;
|
||||||
private final ChunkGenerator generator;
|
private final ChunkGenerator generator;
|
||||||
private final TerraMinestomWorld world;
|
|
||||||
|
|
||||||
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) {
|
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) {
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
this.world = world;
|
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkGenerator getGenerator() {
|
public ChunkGenerator getGenerator() {
|
||||||
@@ -24,13 +25,10 @@ public class MinestomChunkGeneratorWrapper implements Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(@NotNull GenerationUnit generationUnit) {
|
public void generate(@NotNull GenerationUnit unit) {
|
||||||
MinestomProtoChunk protoChunk = new MinestomProtoChunk(
|
Point start = unit.absoluteStart();
|
||||||
world.getMaxHeight(),
|
CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ());
|
||||||
world.getMinHeight(),
|
|
||||||
generationUnit.modifier()
|
chunk.writeRelative(unit.modifier());
|
||||||
);
|
|
||||||
Point start = generationUnit.absoluteStart();
|
|
||||||
generator.generateChunkData(protoChunk, world, world.getBiomeProvider(), start.chunkX(), start.chunkZ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.dfsek.terra.minestom.world;
|
||||||
|
|
||||||
|
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.world.ServerWorld;
|
||||||
|
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||||
|
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||||
|
|
||||||
|
|
||||||
|
public class MinestomProtoWorld implements ProtoWorld {
|
||||||
|
@Override
|
||||||
|
public int centerChunkX() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int centerChunkZ() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerWorld getWorld() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(int x, int y, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkGenerator getGenerator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BiomeProvider getBiomeProvider() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigPack getPack() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getHandle() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -20,22 +20,23 @@ import net.minestom.server.world.DimensionType;
|
|||||||
|
|
||||||
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
|
public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
|
||||||
private final Instance instance;
|
private final Instance instance;
|
||||||
private final MinestomChunkGeneratorWrapper wrapper;
|
|
||||||
private final ConfigPack pack;
|
private final ConfigPack pack;
|
||||||
private final long seed;
|
private final long seed;
|
||||||
private final DimensionType dimensionType;
|
private final DimensionType dimensionType;
|
||||||
|
private final MinestomChunkGeneratorWrapper wrapper;
|
||||||
|
|
||||||
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) {
|
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.wrapper = new MinestomChunkGeneratorWrapper(
|
|
||||||
pack.getGeneratorProvider().newInstance(pack),
|
|
||||||
this
|
|
||||||
);
|
|
||||||
this.pack = pack;
|
this.pack = pack;
|
||||||
this.seed = seed;
|
this.seed = seed;
|
||||||
|
|
||||||
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
|
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
|
||||||
|
|
||||||
|
this.wrapper = new MinestomChunkGeneratorWrapper(
|
||||||
|
pack.getGeneratorProvider().newInstance(pack),
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
instance.setGenerator(this.wrapper);
|
instance.setGenerator(this.wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,4 +99,8 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
|
|||||||
public Object getHandle() {
|
public Object getHandle() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DimensionType getDimensionType() {
|
||||||
|
return dimensionType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user