feat: get faster generation times

This commit is contained in:
Christian Bergschneider 2025-01-02 00:48:26 +01:00
parent d1f881ca2c
commit 23b846eca9
No known key found for this signature in database
GPG Key ID: 3991F97F5FA28D3E
5 changed files with 39 additions and 13 deletions

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.minestom; package com.dfsek.terra.minestom;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
@ -12,6 +13,7 @@ import net.minestom.server.instance.Instance;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -19,10 +21,12 @@ public class TerraMinestomExample {
private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class);
private final MinecraftServer server = MinecraftServer.init(); private final MinecraftServer server = MinecraftServer.init();
private final Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); private final Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer();
private TerraMinestomWorld world;
public void attachTerra() { public void attachTerra() {
TerraMinestomWorldBuilder.from(instance) world = TerraMinestomWorldBuilder.from(instance)
.defaultPack() .defaultPack()
.seed(0)
.attach(); .attach();
} }
@ -37,7 +41,7 @@ public class TerraMinestomExample {
} }
public void preloadWorldAndMeasure() { public void preloadWorldAndMeasure() {
int radius = 6; int radius = 12;
int chunksLoading = (radius * 2 + 1) * (radius * 2 + 1); int chunksLoading = (radius * 2 + 1) * (radius * 2 + 1);
AtomicInteger chunksLeft = new AtomicInteger(chunksLoading); AtomicInteger chunksLeft = new AtomicInteger(chunksLoading);
@ -56,6 +60,8 @@ public class TerraMinestomExample {
(end - start) / 1000000.0, (end - start) / 1000000.0,
chunksPerSecond chunksPerSecond
); );
world.displayStats();
} else if (left % 20 == 0) { } else if (left % 20 == 0) {
sendProgressBar(chunksLoading - left, chunksLoading); sendProgressBar(chunksLoading - left, chunksLoading);
} }
@ -75,6 +81,12 @@ public class TerraMinestomExample {
}); });
} }
public void addScheduler() {
MinecraftServer.getSchedulerManager().buildTask(() -> world.displayStats())
.repeat(Duration.ofSeconds(10))
.schedule();
}
public void bind() { public void bind() {
logger.info("Starting server on port 25565"); logger.info("Starting server on port 25565");
server.start("localhost", 25565); server.start("localhost", 25565);
@ -84,6 +96,7 @@ public class TerraMinestomExample {
TerraMinestomExample example = new TerraMinestomExample(); TerraMinestomExample example = new TerraMinestomExample();
example.attachTerra(); example.attachTerra();
example.preloadWorldAndMeasure(); example.preloadWorldAndMeasure();
example.addScheduler();
example.addListeners(); example.addListeners();
example.bind(); example.bind();
} }

View File

@ -8,10 +8,14 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
import net.minestom.server.world.DimensionType; import net.minestom.server.world.DimensionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GeneratedChunkCache { public class GeneratedChunkCache {
private static final Logger log = LoggerFactory.getLogger(GeneratedChunkCache.class);
private final LoadingCache<Pair<Integer, Integer>, CachedChunk> cache; private final LoadingCache<Pair<Integer, Integer>, CachedChunk> cache;
private final DimensionType dimensionType; private final DimensionType dimensionType;
private final ChunkGenerator generator; private final ChunkGenerator generator;
@ -24,7 +28,8 @@ public class GeneratedChunkCache {
this.world = world; this.world = world;
this.biomeProvider = world.getBiomeProvider(); this.biomeProvider = world.getBiomeProvider();
this.cache = Caffeine.newBuilder() this.cache = Caffeine.newBuilder()
.maximumSize(32) .maximumSize(128)
.recordStats()
.build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight())); .build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
} }
@ -39,6 +44,11 @@ public class GeneratedChunkCache {
return chunk; return chunk;
} }
public void displayStats() {
CacheStats stats = cache.stats();
log.info("Avg load time: {}ms | Hit rate: {}% | Load Count: {}", stats.averageLoadPenalty(), stats.hitRate() * 100, stats.loadCount());
}
public CachedChunk at(int x, int z) { public CachedChunk at(int x, int z) {
return cache.get(Pair.of(x, z)); return cache.get(Pair.of(x, z));
} }

View File

@ -31,13 +31,7 @@ public class MinestomChunkGeneratorWrapper implements Generator {
public void generate(@NotNull GenerationUnit unit) { public void generate(@NotNull GenerationUnit unit) {
Point start = unit.absoluteStart(); Point start = unit.absoluteStart();
CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ()); CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ());
chunk.writeRelative(unit.modifier()); chunk.writeRelative(unit.modifier());
//if (start.chunkX() % 2 == 0 && start.chunkZ() % 2 == 0) {
//chunk.writeRelative(unit.modifier());
//}
unit.fork(setter -> { unit.fork(setter -> {
MinestomProtoWorld protoWorld = new MinestomProtoWorld( MinestomProtoWorld protoWorld = new MinestomProtoWorld(
cache, cache,
@ -52,4 +46,8 @@ public class MinestomChunkGeneratorWrapper implements Generator {
} }
}); });
} }
public void displayStats() {
cache.displayStats();
}
} }

View File

@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; 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.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.minestom.chunk.CachedChunk;
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
import com.dfsek.terra.minestom.entity.DeferredMinestomEntity; import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
@ -21,14 +22,14 @@ public class MinestomProtoWorld implements ProtoWorld {
private final GeneratedChunkCache cache; private final GeneratedChunkCache cache;
private final int x; private final int x;
private final int z; private final int z;
private final ServerWorld world; private final TerraMinestomWorld world;
private final Setter modifier; private final Setter modifier;
public MinestomProtoWorld( public MinestomProtoWorld(
GeneratedChunkCache cache, GeneratedChunkCache cache,
int x, int x,
int z, int z,
ServerWorld world, TerraMinestomWorld world,
Setter modifier Setter modifier
) { ) {
this.cache = cache; this.cache = cache;
@ -74,8 +75,8 @@ public class MinestomProtoWorld implements ProtoWorld {
public BlockState getBlockState(int x, int y, int z) { public BlockState getBlockState(int x, int y, int z) {
int chunkX = x >> 4; int chunkX = x >> 4;
int chunkZ = z >> 4; int chunkZ = z >> 4;
return cache.at(chunkX, chunkZ) CachedChunk chunk = cache.at(chunkX, chunkZ);
.getBlock(x & 15, y, z & 15); return chunk.getBlock(x & 15, y, z & 15);
} }
@Override @Override

View File

@ -67,6 +67,10 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
return MinestomEntity.spawn(x, y, z, entityType, this); return MinestomEntity.spawn(x, y, z, entityType, this);
} }
public void displayStats() {
wrapper.displayStats();
}
@Override @Override
public BlockState getBlockState(int x, int y, int z) { public BlockState getBlockState(int x, int y, int z) {
return new MinestomBlockState(instance.getBlock(x, y, z)); return new MinestomBlockState(instance.getBlock(x, y, z));