From 89cbab071f9c976fa21303caa8611cf7e7bce8dc Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Mon, 30 Jun 2025 00:33:42 +0200 Subject: [PATCH] refactor: remove fine-grained biome controls and adjust biome handling Removed the deprecated `doFineGrainedBiomes` option from `TerraMinestomWorldBuilder` and associated classes. Updated biome management to use `IdentityHashMap` and added additional tracking for created biomes. Upgraded Minestom version to `1_21_6-a40d7115d4`. --- buildSrc/src/main/kotlin/Versions.kt | 2 +- .../terra/minestom/TerraMinestomExample.java | 1 - .../api/TerraMinestomWorldBuilder.java | 16 +------ .../biome/MinestomUserDefinedBiomePool.java | 16 ++++--- .../minestom/biome/UserDefinedBiome.java | 42 ++++++++++++++++- .../world/MinestomChunkGeneratorWrapper.java | 45 +++++++++++-------- .../minestom/world/TerraMinestomWorld.java | 7 +-- 7 files changed, 82 insertions(+), 47 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index e0ec343e3..abb49469e 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -89,6 +89,6 @@ object Versions { } object Minestom { - const val minestom = "1_21_6-c3ccee696b" + const val minestom = "1_21_6-a40d7115d4" } } diff --git a/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 69bcb1680..ccf7ddd9f 100644 --- a/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -44,7 +44,6 @@ public class TerraMinestomExample { public void attachTerra() { world = platform.worldBuilder(instance) .defaultPack() - .doFineGrainedBiomes(false) .attach(); } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/TerraMinestomWorldBuilder.java index 7652a2473..d70a32bdd 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/TerraMinestomWorldBuilder.java @@ -22,7 +22,6 @@ public class TerraMinestomWorldBuilder { private EntityFactory entityFactory = new DefaultEntityFactory(); private BlockEntityFactory blockEntityFactory; private BiomeFactory biomeFactory = new MinestomUserDefinedBiomeFactory(); - private boolean doFineGrainedBiomes = true; public TerraMinestomWorldBuilder(TerraMinestomPlatform platform, Instance instance) { this.platform = platform; @@ -70,20 +69,7 @@ public class TerraMinestomWorldBuilder { return this; } - /** - * Due to a current bug with the minestom biome encoder, sometimes, the client gets kicked when decoding a chunk - * packet with more than one biome. Until this is fixed in minestom, one can disable fine-grained biomes to prevent - * this issue. - * - * @deprecated Scheduled for removal once Minestom rolls out a fix - */ - @Deprecated - public TerraMinestomWorldBuilder doFineGrainedBiomes(boolean doFineGrainedBiomes) { - this.doFineGrainedBiomes = doFineGrainedBiomes; - return this; - } - public TerraMinestomWorld attach() { - return new TerraMinestomWorld(platform, instance, pack, seed, entityFactory, blockEntityFactory, biomeFactory, doFineGrainedBiomes); + return new TerraMinestomWorld(platform, instance, pack, seed, entityFactory, blockEntityFactory, biomeFactory); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomUserDefinedBiomePool.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomUserDefinedBiomePool.java index f5aee7fb8..76d4299a8 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomUserDefinedBiomePool.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomUserDefinedBiomePool.java @@ -1,6 +1,8 @@ package com.dfsek.terra.minestom.biome; import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.Biome; @@ -8,7 +10,8 @@ import com.dfsek.terra.minestom.api.BiomeFactory; public class MinestomUserDefinedBiomePool { - private final HashMap biomes = new HashMap<>(); + private final IdentityHashMap biomes = new IdentityHashMap<>(); + private final HashSet createdBiomes = new HashSet<>(); private final BiomeFactory factory; private final ConfigPack configPack; @@ -18,18 +21,21 @@ public class MinestomUserDefinedBiomePool { } public UserDefinedBiome getBiome(Biome source) { - UserDefinedBiome userDefinedBiome = biomes.get(source.getID()); + UserDefinedBiome userDefinedBiome = biomes.get(source); if(userDefinedBiome != null) return userDefinedBiome; userDefinedBiome = factory.create(configPack, source); - biomes.put(source.getID(), userDefinedBiome); + biomes.put(source, userDefinedBiome); + createdBiomes.add(source.getID()); return userDefinedBiome; } public void preloadBiomes(Iterable biomesToLoad) { biomesToLoad .forEach(biome -> { - if(!this.biomes.containsKey(biome.getID())) { - this.biomes.put(biome.getID(), factory.create(configPack, biome)); + if(!this.createdBiomes.contains(biome.getID())) { + UserDefinedBiome udf = factory.create(configPack, biome); + this.biomes.put(biome, udf); + this.createdBiomes.add(biome.getID()); } }); } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/UserDefinedBiome.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/UserDefinedBiome.java index 86515d810..40b25cfd3 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/UserDefinedBiome.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/UserDefinedBiome.java @@ -1,9 +1,49 @@ package com.dfsek.terra.minestom.biome; import net.kyori.adventure.key.Key; +import net.minestom.server.MinecraftServer; +import net.minestom.server.registry.DynamicRegistry; import net.minestom.server.registry.RegistryKey; import net.minestom.server.world.biome.Biome; -public record UserDefinedBiome(Key key, RegistryKey registry, String id, Biome biome) { +public class UserDefinedBiome { + private static final DynamicRegistry BIOME_REGISTRY = MinecraftServer.getBiomeRegistry(); + + private final Key key; + private final RegistryKey registry; + private final String id; + private final Biome biome; + + private int registryId = -1; + + public UserDefinedBiome(Key key, RegistryKey registry, String id, Biome biome) { + this.key = key; + this.registry = registry; + this.id = id; + this.biome = biome; + } + + public Key key() { + return key; + } + + public RegistryKey registryKey() { + return registry; + } + + public String id() { + return id; + } + + public Biome biome() { + return biome; + } + + public int registryId() { + if(registryId == -1) { + registryId = BIOME_REGISTRY.getId(registry); + } + return registryId; + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java index 4f20d6ec2..2dfa6d18f 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java @@ -1,9 +1,13 @@ package com.dfsek.terra.minestom.world; 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.Generator; +import net.minestom.server.instance.generator.GeneratorImpl.AreaModifierImpl; +import net.minestom.server.instance.generator.GeneratorImpl.SectionModifierImpl; import net.minestom.server.instance.generator.UnitModifier; +import net.minestom.server.instance.palette.Palette; import org.jetbrains.annotations.NotNull; import com.dfsek.terra.api.Platform; @@ -22,25 +26,21 @@ public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrappe private final GeneratedChunkCache cache; private final TerraMinestomWorld world; private final BiomeProvider biomeProvider; - private final boolean doFineGrainedBiomes; private final MinestomUserDefinedBiomePool biomePool; private ChunkGenerator generator; private ConfigPack pack; public MinestomChunkGeneratorWrapper( - Platform platform, ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack, - MinestomUserDefinedBiomePool biomePool, - boolean doFineGrainedBiomes + MinestomUserDefinedBiomePool biomePool ) { this.generator = generator; this.world = world; this.pack = pack; this.biomePool = biomePool; this.biomeProvider = pack.getBiomeProvider(); - this.doFineGrainedBiomes = doFineGrainedBiomes; this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world, biomeProvider); preloadBiomes(); } @@ -49,6 +49,7 @@ public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrappe return generator; } + @SuppressWarnings("UnstableApiUsage") @Override public void generate(@NotNull GenerationUnit unit) { Point start = unit.absoluteStart(); @@ -56,27 +57,33 @@ public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrappe int z = start.chunkZ(); int blockX = start.blockX(); int blockZ = start.blockZ(); - int minY = world.getMinHeight(); - int maxY = world.getMaxHeight(); CachedChunk chunk = cache.at(x, z); UnitModifier modifier = unit.modifier(); chunk.writeRelative(modifier); - if(doFineGrainedBiomes) { - for(int y = minY; y < maxY; y++) { - for(int absoluteX = blockX; absoluteX < blockX + 16; absoluteX++) { - for(int absoluteZ = blockZ; absoluteZ < blockZ + 16; absoluteZ++) { - UserDefinedBiome userDefinedBiome = biomePool.getBiome( - biomeProvider.getBiome(absoluteX, y, absoluteZ, world.getSeed()) - ); - modifier.setBiome(absoluteX, y, absoluteZ, userDefinedBiome.registry()); + AreaModifierImpl areaModifiers = (AreaModifierImpl) modifier; + for(GenerationUnit section : areaModifiers.sections()) { + SectionModifierImpl sectionModifier = (SectionModifierImpl) section.modifier(); + Palette biomes = sectionModifier.genSection().biomes(); + int minY = section.absoluteStart().blockY(); + for(int relativeX = 0; relativeX < 16; relativeX += 1) { + int absoluteX = blockX + relativeX; + for(int relativeZ = 0; relativeZ < 16; relativeZ += 1) { + int absoluteZ = blockZ + relativeZ; + for(int relativeY = 0; relativeY < 16; relativeY += 1) { + int absoluteY = minY + relativeY; + + if (relativeX % 4 == 0 && relativeY % 4 == 0 && relativeZ % 4 == 0) { + UserDefinedBiome userDefinedBiome = biomePool.getBiome( + biomeProvider.getBiome(absoluteX, absoluteY, absoluteZ, world.getSeed()) + ); + + int registryId = userDefinedBiome.registryId(); + biomes.set(relativeX / 4, relativeY / 4, relativeZ / 4, registryId); + } } } } - } else { - // TODO: remove with feature flag once minestom fixed biome encoding - UserDefinedBiome userDefinedBiome = biomePool.getBiome(biomeProvider.getBiome(blockX, 100, blockZ, world.getSeed())); - modifier.fillBiome(userDefinedBiome.registry()); } unit.fork(setter -> { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java index 9e1529d90..fe272a864 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java @@ -44,8 +44,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { long seed, EntityFactory entityFactory, BlockEntityFactory blockEntityFactory, - BiomeFactory factory, - boolean doFineGrainedBiomes + BiomeFactory factory ) { this.instance = instance; this.pack = pack; @@ -55,12 +54,10 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { this.blockEntityFactory = blockEntityFactory; this.wrapper = new MinestomChunkGeneratorWrapper( - platform, pack.getGeneratorProvider().newInstance(pack), this, pack, - new MinestomUserDefinedBiomePool(pack, factory), - doFineGrainedBiomes + new MinestomUserDefinedBiomePool(pack, factory) ); this.entityFactory = entityFactory;