fix: generation stages not being able to reference eachother

This commit is contained in:
Christian Bergschneider
2025-06-02 00:34:48 +02:00
parent 5dff25670c
commit 5e1c9d8ebe
9 changed files with 86 additions and 23 deletions

View File

@@ -122,12 +122,15 @@ public class TerraMinestomExample {
private void regenerate() {
instance.sendMessage(Component.text("Regenerating world"));
Instance oldInstance = instance;
createNewInstance();
attachTerra();
preloadWorldAndMeasure();
MinecraftServer.getConnectionManager().getOnlinePlayers().forEach(player ->
player.setInstance(instance, new Pos(0, 100, 0))
);
MinecraftServer.getInstanceManager().unregisterInstance(oldInstance);
}
}
}

View File

@@ -2,16 +2,17 @@ package com.dfsek.terra.minestom.biome;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.world.biome.Biome;
public class MinestomBiome implements PlatformBiome {
private final Biome biome;
private final DynamicRegistry.Key<Biome> biome;
public MinestomBiome(Biome biome) { this.biome = biome; }
public MinestomBiome(DynamicRegistry.Key<Biome> biome) { this.biome = biome; }
@Override
public Biome getHandle() {
public DynamicRegistry.Key<Biome> getHandle() {
return biome;
}
}

View File

@@ -8,23 +8,19 @@ import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.world.biome.Biome;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType;
public class MinestomBiomeLoader implements TypeLoader<PlatformBiome> {
private final DynamicRegistry<Biome> biomeRegistry = MinecraftServer.getBiomeRegistry();
@Override
public PlatformBiome load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader,
DepthTracker depthTracker) throws LoadException {
@Subst("name:value")
String id = (String) o;
Key key = Key.key(id);
Biome biome = biomeRegistry.get(key);
if(biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker);
return new MinestomBiome(biome);
return new MinestomBiome(DynamicRegistry.Key.of(key));
}
}

View File

@@ -3,10 +3,16 @@ package com.dfsek.terra.minestom.chunk;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.Column;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.minestom.biome.MinestomBiome;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.UnitModifier;
import org.jetbrains.annotations.NotNull;

View File

@@ -22,13 +22,15 @@ public class GeneratedChunkCache {
private final ServerWorld world;
private final BiomeProvider biomeProvider;
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world) {
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world, BiomeProvider biomeProvider) {
this.dimensionType = dimensionType;
this.generator = generator;
this.world = world;
this.biomeProvider = world.getBiomeProvider();
this.cache = Caffeine.newBuilder().maximumSize(128).recordStats().build(
(Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
this.biomeProvider = biomeProvider;
this.cache = Caffeine.newBuilder()
.maximumSize(128)
.recordStats()
.build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
}
private CachedChunk generateChunk(int x, int z) {
@@ -39,8 +41,13 @@ public class GeneratedChunkCache {
public void displayStats() {
CacheStats stats = cache.stats();
log.info("Avg load time: {}ms | Hit rate: {}% | Load Count: {}", stats.averageLoadPenalty(), stats.hitRate() * 100,
stats.loadCount());
log.info("Avg load time: %.4fms | Hit rate: %3.4f%% | Load Count: %d"
.formatted(
stats.averageLoadPenalty() / 1000000f,
stats.hitRate() * 100,
stats.loadCount()
)
);
}
public CachedChunk at(int x, int z) {

View File

@@ -1,30 +1,41 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.PlatformBiome;
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.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.minestom.biome.MinestomBiome;
import com.dfsek.terra.minestom.chunk.CachedChunk;
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.Generator;
import net.minestom.server.instance.generator.UnitModifier;
import net.minestom.server.registry.DynamicRegistry;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrapper {
private final GeneratedChunkCache cache;
private ChunkGenerator generator;
private final TerraMinestomWorld world;
private final BiomeProvider biomeProvider;
private ConfigPack pack;
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack) {
public MinestomChunkGeneratorWrapper(Platform platform, ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack) {
this.generator = generator;
this.world = world;
this.pack = pack;
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world);
biomeProvider = pack.getBiomeProvider().caching(platform);
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world, biomeProvider);
}
public ChunkGenerator getGenerator() {
@@ -36,14 +47,36 @@ public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrappe
Point start = unit.absoluteStart();
int x = start.chunkX();
int z = start.chunkZ();
int blockX = start.blockX();
int blockZ = start.blockZ();
CachedChunk chunk = cache.at(x, z);
chunk.writeRelative(unit.modifier());
UnitModifier modifier = unit.modifier();
chunk.writeRelative(modifier);
// for(int dx = 0; dx < 16; dx++) {
// for(int dz = 0; dz < 16; dz++) {
// int globalX = dx + blockX;
// int globalZ = dz + blockZ;
// biomeProvider.getColumn(globalX, globalZ, world).forEach((y, biome) -> {
// MinestomBiome platformBiome = (MinestomBiome) biome.getPlatformBiome();
// modifier.setBiome(globalX, 0, globalZ, DynamicRegistry.Key.of("minecraft:the_void"));
// });
// }
// }
unit.fork(setter -> {
MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter);
var stages = world.getPack().getStages();
if(x==0 && z==0) {
System.out.println(stages);
System.out.println(protoWorld.getBlockState(-4, 73, -6).getAsString());
}
for(GenerationStage stage : world.getPack().getStages()) {
stage.populate(protoWorld);
if(x==0 && z==0) System.out.println(protoWorld.getBlockState(-4, 73, -6).getAsString());
}
});
}

View File

@@ -5,6 +5,7 @@ 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.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;
@@ -17,6 +18,11 @@ import com.dfsek.terra.minestom.entity.DeferredMinestomEntity;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.Block.Setter;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.WeakHashMap;
public class MinestomProtoWorld implements ProtoWorld {
private final GeneratedChunkCache cache;
@@ -51,6 +57,10 @@ public class MinestomProtoWorld implements ProtoWorld {
@Override
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
modifier.setBlock(x, y, z, (Block) data.getHandle());
int chunkX = x >> 4;
int chunkZ = z >> 4;
CachedChunk chunk = cache.at(chunkX, chunkZ);
chunk.setBlock(x & 15, y, z & 15, data);
}
@Override

View File

@@ -13,6 +13,7 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.minestom.TerraMinestomPlatform;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import com.dfsek.terra.minestom.api.EntityFactory;
import com.dfsek.terra.minestom.block.MinestomBlockState;
@@ -37,8 +38,14 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
private final EntityFactory entityFactory;
private final BlockEntityFactory blockEntityFactory;
public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory entityFactory,
BlockEntityFactory blockEntityFactory) {
public TerraMinestomWorld(
TerraMinestomPlatform platform,
Instance instance,
ConfigPack pack,
long seed,
EntityFactory entityFactory,
BlockEntityFactory blockEntityFactory
) {
this.instance = instance;
this.pack = pack;
this.seed = seed;
@@ -46,7 +53,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties {
this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType());
this.blockEntityFactory = blockEntityFactory;
this.wrapper = new MinestomChunkGeneratorWrapper(pack.getGeneratorProvider().newInstance(pack), this, pack);
this.wrapper = new MinestomChunkGeneratorWrapper(platform, pack.getGeneratorProvider().newInstance(pack), this, pack);
this.entityFactory = entityFactory;
instance.setGenerator(this.wrapper);

View File

@@ -66,6 +66,6 @@ public class TerraMinestomWorldBuilder {
}
public TerraMinestomWorld attach() {
return new TerraMinestomWorld(instance, pack, seed, entityFactory, blockEntityFactory);
return new TerraMinestomWorld(platform, instance, pack, seed, entityFactory, blockEntityFactory);
}
}