From 983cb1f012a80fcdf5a18e805a0065c0c007f0c1 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 28 Dec 2024 12:22:07 +0100 Subject: [PATCH 01/25] feat: base terrain generation with minestom --- buildSrc/src/main/kotlin/Versions.kt | 4 + platforms/minestom/build.gradle.kts | 34 ++++++ .../terra/minestom/MinestomPlatform.java | 73 +++++++++++++ .../terra/minestom/TerraMinestomExample.java | 38 +++++++ .../minestom/block/MinestomBlockState.java | 95 ++++++++++++++++ .../minestom/block/MinestomBlockType.java | 35 ++++++ .../minestom/chunk/MinestomProtoChunk.java | 49 +++++++++ .../minestom/chunk/TerraMinestomChunk.java | 50 +++++++++ .../minestom/item/MinestomItemHandle.java | 25 +++++ .../world/MinestomChunkGeneratorWrapper.java | 36 +++++++ .../minestom/world/MinestomWorldHandle.java | 29 +++++ .../minestom/world/TerraMinestomWorld.java | 101 ++++++++++++++++++ .../world/TerraMinestomWorldBuilder.java | 58 ++++++++++ 13 files changed, 627 insertions(+) create mode 100644 platforms/minestom/build.gradle.kts create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 1e48e716a..c78008cb3 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -75,4 +75,8 @@ object Versions { const val nbt = "6.1" const val logback = "1.5.8" } + + object Minestom { + const val minestom = "187931e50b" + } } \ No newline at end of file diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts new file mode 100644 index 000000000..ebc442209 --- /dev/null +++ b/platforms/minestom/build.gradle.kts @@ -0,0 +1,34 @@ +plugins { + application +} + +val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample" + +dependencies { + shadedApi(project(":common:implementation:base")) + + //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) + + implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) + implementation("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j) +} + +tasks.withType { + entryCompression = ZipEntryCompression.STORED + manifest { + attributes( + "Main-Class" to javaMainClass, + ) + } +} + +application { + mainClass.set(javaMainClass) +} + +tasks.getByName("run").setProperty("workingDir", file("./run")) + +addonDir(project.file("./run/terra/addons"), tasks.named("run").get()) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java new file mode 100644 index 000000000..2cac94575 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java @@ -0,0 +1,73 @@ +package com.dfsek.terra.minestom; + +import com.dfsek.tectonic.api.TypeRegistry; + +import com.dfsek.tectonic.api.loader.type.TypeLoader; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + +import com.dfsek.terra.minestom.item.MinestomItemHandle; + +import com.dfsek.terra.minestom.world.MinestomWorldHandle; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; + + +public final class MinestomPlatform extends AbstractPlatform { + private static MinestomPlatform INSTANCE = null; + private final MinestomWorldHandle worldHandle = new MinestomWorldHandle(); + private final MinestomItemHandle itemHandle = new MinestomItemHandle(); + + private MinestomPlatform() { + load(); + getEventManager().callEvent(new PlatformInitializationEvent()); + } + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(PlatformBiome.class, (TypeLoader) (annotatedType, o, configLoader, depthTracker) -> () -> o); + } + + @Override + public boolean reload() { + return false; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public @NotNull String platformName() { + return "Minestom"; + } + + @Override + public @NotNull File getDataFolder() { + File file = new File("./terra/"); + if (!file.exists()) file.mkdirs(); + return file; + } + + + public static MinestomPlatform getInstance() { + if (INSTANCE == null) { + INSTANCE = new MinestomPlatform(); + } + return INSTANCE; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java new file mode 100644 index 000000000..934f5a220 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -0,0 +1,38 @@ +package com.dfsek.terra.minestom; + +import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.GameMode; +import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; +import net.minestom.server.instance.Instance; + + +public class TerraMinestomExample { + public static void main(String[] args) { + MinecraftServer server = MinecraftServer.init(); + + Instance instance = MinecraftServer + .getInstanceManager() + .createInstanceContainer(); + + TerraMinestomWorldBuilder.from(instance) + .packById("OVERWORLD") + .attach(); + + for(int x = -1; x <= 1; x++) { + for(int z = -1; z <= 1; z++) { + instance.loadChunk(x, z); + } + } + + MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> { + event.setSpawningInstance(instance); + event.getPlayer().setGameMode(GameMode.CREATIVE); + event.getPlayer().setRespawnPoint(new Pos(0.0, 100.0, 0.0)); + }); + + server.start("localhost", 25565); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java new file mode 100644 index 000000000..9805be509 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java @@ -0,0 +1,95 @@ +package com.dfsek.terra.minestom.block; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; + +import net.minestom.server.instance.block.Block; + +import java.util.HashMap; +import java.util.Objects; +import java.util.stream.Collectors; + + +public class MinestomBlockState implements BlockState { + private final Block block; + + public MinestomBlockState(Block block) { + this.block = block; + } + + public MinestomBlockState(String data) { + if (!data.contains("[")) { + block = Block.fromNamespaceId(data); + return; + } + + String[] split = data.split("\\["); + String namespaceId = split[0]; + String properties = split[1].substring(0, split[1].length() - 1); + Block block = Block.fromNamespaceId(namespaceId); + HashMap propertiesMap = new HashMap<>(); + + for (String property : properties.split(",")) { + String[] kv = property.split("="); + propertiesMap.put(kv[0].strip(), kv[1].strip()); + } + + assert block != null; + this.block = block.withProperties(propertiesMap); + } + + @Override + public boolean matches(BlockState other) { + return ((MinestomBlockState) other).block == block; + } + + @Override + public > boolean has(Property property) { + return false; + } + + @Override + public > T get(Property property) { + return null; + } + + @Override + public > BlockState set(Property property, T value) { + return null; + } + + @Override + public BlockType getBlockType() { + return new MinestomBlockType(block); + } + + @Override + public String getAsString(boolean properties) { + String name = block.namespace().asString(); + if (!properties) { + return name; + } + + name += "[" + block + .properties() + .entrySet() + .stream() + .map(entry -> + entry.getKey() + "=" + entry.getValue() + ) + .collect(Collectors.joining(",")) + "]"; + + return name; + } + + @Override + public boolean isAir() { + return block.isAir(); + } + + @Override + public Object getHandle() { + return block; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java new file mode 100644 index 000000000..fd447649f --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.minestom.block; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; + +import net.minestom.server.instance.block.Block; + + +public class MinestomBlockType implements BlockType { + private final Block block; + + public MinestomBlockType(Block block) { + this.block = block; + } + + @Override + public BlockState getDefaultState() { + return new MinestomBlockState(block); + } + + @Override + public boolean isSolid() { + return block.isSolid(); + } + + @Override + public boolean isWater() { + return block.isLiquid(); + } + + @Override + public Object getHandle() { + return block; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java new file mode 100644 index 000000000..3e658c88a --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java @@ -0,0 +1,49 @@ +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; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java new file mode 100644 index 000000000..12f38ced3 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.minestom.chunk; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; + +import com.dfsek.terra.minestom.block.MinestomBlockState; +import net.minestom.server.instance.block.Block; +import org.jetbrains.annotations.NotNull; + + +public class TerraMinestomChunk implements Chunk { + private net.minestom.server.instance.Chunk delegate; + private final ServerWorld world; + + public TerraMinestomChunk(net.minestom.server.instance.Chunk delegate, ServerWorld world) { + this.delegate = delegate; + this.world = world; + } + + @Override + public void setBlock(int x, int y, int z, BlockState data, boolean physics) { + delegate.setBlock(x, y, z, (Block) data.getHandle()); + } + + @Override + public @NotNull BlockState getBlock(int x, int y, int z) { + return new MinestomBlockState(delegate.getBlock(x, y, z)); + } + + @Override + public int getX() { + return delegate.getChunkX(); + } + + @Override + public int getZ() { + return delegate.getChunkZ(); + } + + @Override + public ServerWorld getWorld() { + return world; + } + + @Override + public Object getHandle() { + return delegate; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java new file mode 100644 index 000000000..65ddb1605 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.minestom.item; + +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; + +import java.util.Set; + + +public class MinestomItemHandle implements ItemHandle { + @Override + public Item createItem(String data) { + return null; + } + + @Override + public Enchantment getEnchantment(String id) { + return null; + } + + @Override + public Set getEnchantments() { + return Set.of(); + } +} 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 new file mode 100644 index 000000000..6c106d16d --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomChunkGeneratorWrapper.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.minestom.world; + +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; + +import com.dfsek.terra.minestom.chunk.MinestomProtoChunk; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.instance.generator.GenerationUnit; +import net.minestom.server.instance.generator.Generator; +import org.jetbrains.annotations.NotNull; + + +public class MinestomChunkGeneratorWrapper implements Generator { + private final ChunkGenerator generator; + private final TerraMinestomWorld world; + + public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) { + this.generator = generator; + this.world = world; + } + + public ChunkGenerator getGenerator() { + return generator; + } + + @Override + public void generate(@NotNull GenerationUnit generationUnit) { + MinestomProtoChunk protoChunk = new MinestomProtoChunk( + world.getMaxHeight(), + world.getMinHeight(), + generationUnit.modifier() + ); + Point start = generationUnit.absoluteStart(); + generator.generateChunkData(protoChunk, world, world.getBiomeProvider(), start.chunkX(), start.chunkZ()); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java new file mode 100644 index 000000000..eb5731bb4 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.minestom.world; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; + +import com.dfsek.terra.minestom.block.MinestomBlockState; +import net.minestom.server.instance.block.Block; +import org.jetbrains.annotations.NotNull; + + +public class MinestomWorldHandle implements WorldHandle { + private static final MinestomBlockState AIR = new MinestomBlockState(Block.AIR); + + @Override + public @NotNull BlockState createBlockState(@NotNull String data) { + return new MinestomBlockState(data); + } + + @Override + public @NotNull BlockState air() { + return AIR; + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { + return null; + } +} 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 new file mode 100644 index 000000000..694e80b87 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorld.java @@ -0,0 +1,101 @@ +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.Chunk; + +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; + +import com.dfsek.terra.api.world.info.WorldProperties; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.instance.Instance; +import net.minestom.server.world.DimensionType; + + +public final class TerraMinestomWorld implements ServerWorld, WorldProperties { + private final Instance instance; + private final MinestomChunkGeneratorWrapper wrapper; + private final ConfigPack pack; + private final long seed; + private final DimensionType dimensionType; + + public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) { + this.instance = instance; + this.wrapper = new MinestomChunkGeneratorWrapper( + pack.getGeneratorProvider().newInstance(pack), + this + ); + this.pack = pack; + this.seed = seed; + + this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType()); + + instance.setGenerator(this.wrapper); + } + + @Override + public Chunk getChunkAt(int x, int z) { + 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 wrapper.getGenerator(); + } + + @Override + public BiomeProvider getBiomeProvider() { + return pack.getBiomeProvider(); + } + + @Override + public ConfigPack getPack() { + return pack; + } + + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return dimensionType.maxY(); + } + + @Override + public int getMinHeight() { + return dimensionType.minY(); + } + + @Override + public Object getHandle() { + return instance; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java new file mode 100644 index 000000000..b50d9c9c5 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.minestom.world; + +import com.dfsek.terra.api.config.ConfigPack; + +import com.dfsek.terra.api.registry.CheckedRegistry; + +import com.dfsek.terra.minestom.MinestomPlatform; +import net.minestom.server.MinecraftServer; +import net.minestom.server.instance.Instance; + +import java.util.Random; +import java.util.function.Function; + + +public class TerraMinestomWorldBuilder { + private final Instance instance; + private ConfigPack pack; + private long seed = new Random().nextLong(); + + private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; } + + public static TerraMinestomWorldBuilder from(Instance instance) { + return new TerraMinestomWorldBuilder(instance); + } + + public static TerraMinestomWorldBuilder builder() { + return new TerraMinestomWorldBuilder(MinecraftServer.getInstanceManager().createInstanceContainer()); + } + + public TerraMinestomWorldBuilder pack(ConfigPack pack) { + this.pack = pack; + return this; + } + + public TerraMinestomWorldBuilder packById(String id) { + this.pack = MinestomPlatform + .getInstance() + .getConfigRegistry() + .getByID(id) + .orElseThrow(); + + return this; + } + + public TerraMinestomWorldBuilder findPack(Function, ConfigPack> fn) { + this.pack = fn.apply(MinestomPlatform.getInstance().getConfigRegistry()); + return this; + } + + public TerraMinestomWorldBuilder seed(long seed) { + this.seed = seed; + return this; + } + + public TerraMinestomWorld attach() { + return new TerraMinestomWorld(instance, pack, seed); + } +} From 7288373dbc9fe4ad7ed0624448148063937c1805 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 28 Dec 2024 18:18:17 +0100 Subject: [PATCH 02/25] feat: cache generated chunks This commit is in preparation of multi-layered worldgen with minestom --- platforms/minestom/build.gradle.kts | 5 +- .../minestom/block/MinestomBlockState.java | 7 +- .../terra/minestom/chunk/CachedChunk.java | 57 +++++++++++++ .../minestom/chunk/GeneratedChunkCache.java | 45 ++++++++++ .../minestom/chunk/MinestomProtoChunk.java | 49 ----------- .../world/MinestomChunkGeneratorWrapper.java | 20 ++--- .../minestom/world/MinestomProtoWorld.java | 84 +++++++++++++++++++ .../minestom/world/TerraMinestomWorld.java | 15 ++-- 8 files changed, 211 insertions(+), 71 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts index ebc442209..b1fb58dfd 100644 --- a/platforms/minestom/build.gradle.kts +++ b/platforms/minestom/build.gradle.kts @@ -6,10 +6,7 @@ val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample" dependencies { shadedApi(project(":common:implementation:base")) - - //shadedApi("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO) - //shadedApi("com.github.Querz", "NBT", Versions.CLI.nbt) - + shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine) shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava) implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java index 9805be509..55da9dfa7 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java @@ -7,7 +7,6 @@ import com.dfsek.terra.api.block.state.properties.Property; import net.minestom.server.instance.block.Block; import java.util.HashMap; -import java.util.Objects; import java.util.stream.Collectors; @@ -15,7 +14,11 @@ public class MinestomBlockState implements BlockState { private final Block block; public MinestomBlockState(Block block) { - this.block = block; + if (block == null) { + this.block = Block.AIR; + } else { + this.block = block; + } } public MinestomBlockState(String data) { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java new file mode 100644 index 000000000..5a57f9830 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java @@ -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; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java new file mode 100644 index 000000000..db711d086 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java @@ -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, 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 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)); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java deleted file mode 100644 index 3e658c88a..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/MinestomProtoChunk.java +++ /dev/null @@ -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; - } -} 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 6c106d16d..dcb6c6f0b 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 @@ -2,7 +2,8 @@ package com.dfsek.terra.minestom.world; 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.instance.generator.GenerationUnit; @@ -11,12 +12,12 @@ import org.jetbrains.annotations.NotNull; public class MinestomChunkGeneratorWrapper implements Generator { + private final GeneratedChunkCache cache; private final ChunkGenerator generator; - private final TerraMinestomWorld world; public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) { this.generator = generator; - this.world = world; + this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world); } public ChunkGenerator getGenerator() { @@ -24,13 +25,10 @@ public class MinestomChunkGeneratorWrapper implements Generator { } @Override - public void generate(@NotNull GenerationUnit generationUnit) { - MinestomProtoChunk protoChunk = new MinestomProtoChunk( - world.getMaxHeight(), - world.getMinHeight(), - generationUnit.modifier() - ); - Point start = generationUnit.absoluteStart(); - generator.generateChunkData(protoChunk, world, world.getBiomeProvider(), start.chunkX(), start.chunkZ()); + public void generate(@NotNull GenerationUnit unit) { + Point start = unit.absoluteStart(); + CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ()); + + chunk.writeRelative(unit.modifier()); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java new file mode 100644 index 000000000..4299ee216 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -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; + } +} 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 694e80b87..aac669a32 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 @@ -20,22 +20,23 @@ import net.minestom.server.world.DimensionType; public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final Instance instance; - private final MinestomChunkGeneratorWrapper wrapper; private final ConfigPack pack; private final long seed; private final DimensionType dimensionType; + private final MinestomChunkGeneratorWrapper wrapper; public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) { this.instance = instance; - this.wrapper = new MinestomChunkGeneratorWrapper( - pack.getGeneratorProvider().newInstance(pack), - this - ); this.pack = pack; this.seed = seed; this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType()); + this.wrapper = new MinestomChunkGeneratorWrapper( + pack.getGeneratorProvider().newInstance(pack), + this + ); + instance.setGenerator(this.wrapper); } @@ -98,4 +99,8 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { public Object getHandle() { return instance; } + + public DimensionType getDimensionType() { + return dimensionType; + } } From f953c5085db4714ac3139d6214690a761d5b6f59 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 28 Dec 2024 20:05:50 +0100 Subject: [PATCH 03/25] feat: start generating features --- .../world/MinestomChunkGeneratorWrapper.java | 19 ++++++- .../minestom/world/MinestomProtoWorld.java | 51 ++++++++++++++----- 2 files changed, 57 insertions(+), 13 deletions(-) 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 dcb6c6f0b..d84c143a5 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 @@ -2,6 +2,7 @@ package com.dfsek.terra.minestom.world; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.minestom.chunk.CachedChunk; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; @@ -14,9 +15,11 @@ import org.jetbrains.annotations.NotNull; public class MinestomChunkGeneratorWrapper implements Generator { private final GeneratedChunkCache cache; private final ChunkGenerator generator; + private final TerraMinestomWorld world; public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) { this.generator = generator; + this.world = world; this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world); } @@ -29,6 +32,20 @@ public class MinestomChunkGeneratorWrapper implements Generator { Point start = unit.absoluteStart(); CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ()); - chunk.writeRelative(unit.modifier()); + //chunk.writeRelative(unit.modifier()); + + unit.fork(setter -> { + MinestomProtoWorld protoWorld = new MinestomProtoWorld( + cache, + start.chunkX(), + start.chunkZ(), + world, + setter + ); + + for(GenerationStage stage : world.getPack().getStages()) { + stage.populate(protoWorld); + } + }); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index 4299ee216..5fe0aa99c 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -9,27 +9,51 @@ 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; +import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; + +import net.minestom.server.instance.block.Block; +import net.minestom.server.instance.block.Block.Setter; public class MinestomProtoWorld implements ProtoWorld { + private final GeneratedChunkCache cache; + private final int x; + private final int z; + private final ServerWorld world; + private final Setter modifier; + + public MinestomProtoWorld( + GeneratedChunkCache cache, + int x, + int z, + ServerWorld world, + Setter modifier + ) { + this.cache = cache; + this.x = x; + this.z = z; + this.world = world; + this.modifier = modifier; + } + @Override public int centerChunkX() { - return 0; + return x; } @Override public int centerChunkZ() { - return 0; + return z; } @Override public ServerWorld getWorld() { - return null; + return world; } @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - + modifier.setBlock(this.x * 16 + x, y, this.z * 16 + z, (Block) data.getHandle()); } @Override @@ -39,7 +63,10 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public BlockState getBlockState(int x, int y, int z) { - return null; + int chunkX = x >> 4; + int chunkZ = z >> 4; + return cache.at(chunkX + this.x, chunkZ + this.z) + .getBlock(x & 15, y, z & 15); } @Override @@ -49,36 +76,36 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public ChunkGenerator getGenerator() { - return null; + return world.getGenerator(); } @Override public BiomeProvider getBiomeProvider() { - return null; + return world.getBiomeProvider(); } @Override public ConfigPack getPack() { - return null; + return world.getPack(); } @Override public long getSeed() { - return 0; + return world.getSeed(); } @Override public int getMaxHeight() { - return 0; + return world.getMaxHeight(); } @Override public int getMinHeight() { - return 0; + return world.getMinHeight(); } @Override public Object getHandle() { - return null; + return world; } } From fa6e0e0ae406ee7777791c9828fff51f58c690cb Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 28 Dec 2024 21:41:51 +0100 Subject: [PATCH 04/25] feat: feature generation but only in even chunks --- .../com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java | 4 ++-- .../terra/minestom/world/MinestomChunkGeneratorWrapper.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java index db711d086..31eb2b7f9 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java @@ -39,7 +39,7 @@ public class GeneratedChunkCache { return chunk; } - public CachedChunk at(int x, int y) { - return cache.get(Pair.of(x, y)); + public CachedChunk at(int x, int z) { + return cache.get(Pair.of(x, z)); } } 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 d84c143a5..9bec88c86 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 @@ -34,6 +34,10 @@ public class MinestomChunkGeneratorWrapper implements Generator { //chunk.writeRelative(unit.modifier()); + if (start.chunkX() % 2 == 0 && start.chunkZ() % 2 == 0) { + chunk.writeRelative(unit.modifier()); + } + unit.fork(setter -> { MinestomProtoWorld protoWorld = new MinestomProtoWorld( cache, From bfc1c32d46baebd87095f9846d953e15fc9a4f8e Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 29 Dec 2024 15:17:35 +0100 Subject: [PATCH 05/25] feat: surface decoration generation but only in even chunks --- .../java/com/dfsek/terra/api/block/BlockType.java | 3 +++ .../dfsek/terra/minestom/TerraMinestomExample.java | 3 ++- .../terra/minestom/block/MinestomBlockState.java | 10 ++++++++-- .../terra/minestom/block/MinestomBlockType.java | 13 +++++++++++++ .../world/MinestomChunkGeneratorWrapper.java | 8 ++++---- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java index 62b117e7b..3585a50af 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java @@ -13,6 +13,9 @@ import com.dfsek.terra.api.block.state.BlockState; /** * Represents a type of block + *

+ * Important! You need to implement a proper equals() and hashCode() here in + * your platform implementation for surface decorations to show up */ public interface BlockType extends Handle { /** diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 934f5a220..b55ada3d0 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -18,7 +18,8 @@ public class TerraMinestomExample { .createInstanceContainer(); TerraMinestomWorldBuilder.from(instance) - .packById("OVERWORLD") + .packById("DEFMOD") + .seed(0) .attach(); for(int x = -1; x <= 1; x++) { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java index 55da9dfa7..cc455e133 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java @@ -7,6 +7,7 @@ import com.dfsek.terra.api.block.state.properties.Property; import net.minestom.server.instance.block.Block; import java.util.HashMap; +import java.util.Objects; import java.util.stream.Collectors; @@ -44,7 +45,7 @@ public class MinestomBlockState implements BlockState { @Override public boolean matches(BlockState other) { - return ((MinestomBlockState) other).block == block; + return ((MinestomBlockState) other).block.compare(block); } @Override @@ -70,7 +71,7 @@ public class MinestomBlockState implements BlockState { @Override public String getAsString(boolean properties) { String name = block.namespace().asString(); - if (!properties) { + if (!properties || block.properties().isEmpty()) { return name; } @@ -95,4 +96,9 @@ public class MinestomBlockState implements BlockState { public Object getHandle() { return block; } + + @Override + public int hashCode() { + return Objects.hashCode(block.id()); + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java index fd447649f..36c5ce42d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java @@ -32,4 +32,17 @@ public class MinestomBlockType implements BlockType { public Object getHandle() { return block; } + + @Override + public int hashCode() { + return block.id(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MinestomBlockType other) { + return block.id() == other.block.id(); + } + return false; + } } 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 9bec88c86..fd48e874f 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 @@ -32,11 +32,11 @@ public class MinestomChunkGeneratorWrapper implements Generator { Point start = unit.absoluteStart(); 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()); - } + //if (start.chunkX() % 2 == 0 && start.chunkZ() % 2 == 0) { + //chunk.writeRelative(unit.modifier()); + //} unit.fork(setter -> { MinestomProtoWorld protoWorld = new MinestomProtoWorld( From ac66fc7d69299936ac03c8881c83e84b6d18aef4 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 29 Dec 2024 15:51:05 +0100 Subject: [PATCH 06/25] fix: different populators now know about each other --- .../dfsek/terra/minestom/world/MinestomProtoWorld.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index 5fe0aa99c..57cb1c3c5 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -53,7 +53,13 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - modifier.setBlock(this.x * 16 + x, y, this.z * 16 + z, (Block) data.getHandle()); + int globalX = this.x * 16 + x; + int globalZ = this.z * 16 + z; + modifier.setBlock(globalX, y, globalZ, (Block) data.getHandle()); + int cx = globalX >> 4; + int cz = globalZ >> 4; + cache.at(cx, cz) + .setBlock(x & 15, y, z & 15, data); } @Override From 3a28551e97e3556a0e90ee4bc8ff439203a7ed9e Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 29 Dec 2024 18:55:47 +0100 Subject: [PATCH 07/25] fix: generate populators in every chunk --- .../com/dfsek/terra/minestom/TerraMinestomExample.java | 7 ++++++- .../dfsek/terra/minestom/world/MinestomProtoWorld.java | 10 ++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index b55ada3d0..1848c0315 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,11 +1,13 @@ package com.dfsek.terra.minestom; +import com.dfsek.terra.minestom.world.MinestomProtoWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; +import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; @@ -30,10 +32,13 @@ public class TerraMinestomExample { MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> { event.setSpawningInstance(instance); - event.getPlayer().setGameMode(GameMode.CREATIVE); event.getPlayer().setRespawnPoint(new Pos(0.0, 100.0, 0.0)); }); + MinecraftServer.getGlobalEventHandler().addListener(PlayerSpawnEvent.class, event -> { + event.getPlayer().setGameMode(GameMode.SPECTATOR); + }); + server.start("localhost", 25565); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index 57cb1c3c5..628dcf990 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -53,11 +53,9 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - int globalX = this.x * 16 + x; - int globalZ = this.z * 16 + z; - modifier.setBlock(globalX, y, globalZ, (Block) data.getHandle()); - int cx = globalX >> 4; - int cz = globalZ >> 4; + int cx = x >> 4; + int cz = y >> 4; + modifier.setBlock(x, y, z, (Block) data.getHandle()); cache.at(cx, cz) .setBlock(x & 15, y, z & 15, data); } @@ -71,7 +69,7 @@ public class MinestomProtoWorld implements ProtoWorld { public BlockState getBlockState(int x, int y, int z) { int chunkX = x >> 4; int chunkZ = z >> 4; - return cache.at(chunkX + this.x, chunkZ + this.z) + return cache.at(chunkX, chunkZ) .getBlock(x & 15, y, z & 15); } From d5ab3e23f57201308e744120df50e283aa6f1650 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Wed, 1 Jan 2025 18:41:33 +0100 Subject: [PATCH 08/25] feat: better example server --- .../terra/minestom/TerraMinestomExample.java | 70 +++++++++++++++---- .../world/TerraMinestomWorldBuilder.java | 4 ++ 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 1848c0315..c375d48fc 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,35 +1,70 @@ package com.dfsek.terra.minestom; -import com.dfsek.terra.minestom.world.MinestomProtoWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; import net.minestom.server.MinecraftServer; +import net.minestom.server.command.builder.Command; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.atomic.AtomicInteger; public class TerraMinestomExample { - public static void main(String[] args) { - MinecraftServer server = MinecraftServer.init(); - - Instance instance = MinecraftServer - .getInstanceManager() - .createInstanceContainer(); + private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); + private final MinecraftServer server = MinecraftServer.init(); + private final Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + public void attachTerra() { TerraMinestomWorldBuilder.from(instance) - .packById("DEFMOD") - .seed(0) + .defaultPack() .attach(); + } - for(int x = -1; x <= 1; x++) { - for(int z = -1; z <= 1; z++) { - instance.loadChunk(x, z); + private void sendProgressBar(int current, int max) { + String left = "#".repeat((int) ((((float) current)/max) * 20)); + String right = ".".repeat(20 - left.length()); + int percent = (int) (((float) current)/max * 100); + String percentString = percent + "%"; + percentString = " ".repeat(4 - percentString.length()) + percentString; + String message = percentString + " |" + left + right + "| " + current + "/" + max; + logger.info(message); + } + + public void preloadWorldAndMeasure() { + int radius = 6; + int chunksLoading = (radius * 2 + 1) * (radius * 2 + 1); + AtomicInteger chunksLeft = new AtomicInteger(chunksLoading); + + long start = System.nanoTime(); + for(int x = -radius; x <= radius; x++) { + for(int z = -radius; z <= radius; z++) { + instance.loadChunk(x, z).thenAccept(chunk -> { + int left = chunksLeft.decrementAndGet(); + if(left == 0) { + long end = System.nanoTime(); + sendProgressBar(chunksLoading - left, chunksLoading); + double chunksPerSecond = chunksLoading / ((end - start) / 1000000000.0); + logger.info( + "Preloaded {} chunks in world in {}ms. That's {} Chunks/s", + chunksLoading, + (end - start) / 1000000.0, + chunksPerSecond + ); + } else if (left % 20 == 0) { + sendProgressBar(chunksLoading - left, chunksLoading); + } + }); } } + } + public void addListeners() { MinecraftServer.getGlobalEventHandler().addListener(AsyncPlayerConfigurationEvent.class, event -> { event.setSpawningInstance(instance); event.getPlayer().setRespawnPoint(new Pos(0.0, 100.0, 0.0)); @@ -38,7 +73,18 @@ public class TerraMinestomExample { MinecraftServer.getGlobalEventHandler().addListener(PlayerSpawnEvent.class, event -> { event.getPlayer().setGameMode(GameMode.SPECTATOR); }); + } + public void bind() { + logger.info("Starting server on port 25565"); server.start("localhost", 25565); } + + public static void main(String[] args) { + TerraMinestomExample example = new TerraMinestomExample(); + example.attachTerra(); + example.preloadWorldAndMeasure(); + example.addListeners(); + example.bind(); + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index b50d9c9c5..8b70b3a0f 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -47,6 +47,10 @@ public class TerraMinestomWorldBuilder { return this; } + public TerraMinestomWorldBuilder defaultPack() { + return this.packById("OVERWORLD"); + } + public TerraMinestomWorldBuilder seed(long seed) { this.seed = seed; return this; From d1f881ca2c0681f719bb984d853fbf3f1b5baa44 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Wed, 1 Jan 2025 20:39:09 +0100 Subject: [PATCH 09/25] feat: minestom entities --- .../dfsek/terra/minestom/MinestomAdapter.java | 17 +++++ .../terra/minestom/api/EntityFactory.java | 13 ++++ .../minestom/entity/DefaultEntityFactory.java | 14 +++++ .../entity/DeferredMinestomEntity.java | 62 +++++++++++++++++++ .../terra/minestom/entity/MinestomEntity.java | 55 ++++++++++++++++ .../minestom/entity/MinestomEntityType.java | 18 ++++++ .../minestom/world/MinestomProtoWorld.java | 7 ++- .../minestom/world/MinestomWorldHandle.java | 4 +- .../minestom/world/TerraMinestomWorld.java | 32 ++++++++-- .../world/TerraMinestomWorldBuilder.java | 10 ++- 10 files changed, 224 insertions(+), 8 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomAdapter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/EntityFactory.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DefaultEntityFactory.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntity.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntityType.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomAdapter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomAdapter.java new file mode 100644 index 000000000..697997c0b --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomAdapter.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.minestom; + +import com.dfsek.terra.api.util.vector.Vector3; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; + + +public class MinestomAdapter { + public static Vector3 adapt(Point point) { + return Vector3.of(point.x(), point.y(), point.z()); + } + + public static Pos adapt(Vector3 vector) { + return new Pos(vector.getX(), vector.getY(), vector.getZ()); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/EntityFactory.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/EntityFactory.java new file mode 100644 index 000000000..5cfbecd8d --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/EntityFactory.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.minestom.api; + + +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; + + +/** + * Allows adding AI to generated entities using custom entity types + */ +public interface EntityFactory { + Entity createEntity(EntityType type); +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DefaultEntityFactory.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DefaultEntityFactory.java new file mode 100644 index 000000000..23226fc99 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DefaultEntityFactory.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.minestom.entity; + +import com.dfsek.terra.minestom.api.EntityFactory; + +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; + + +public class DefaultEntityFactory implements EntityFactory { + @Override + public Entity createEntity(EntityType type) { + return new Entity(type); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java new file mode 100644 index 000000000..6dfdf5b52 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java @@ -0,0 +1,62 @@ +package com.dfsek.terra.minestom.entity; + +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.minestom.world.TerraMinestomWorld; + + +public class DeferredMinestomEntity implements Entity { + private final EntityType type; + private double x; + private double y; + private double z; + private TerraMinestomWorld world; + + public DeferredMinestomEntity(double x, double y, double z, EntityType type, TerraMinestomWorld world) { + this.x = x; + this.y = y; + this.z = z; + this.type = type; + this.world = world; + } + + @Override + public Vector3 position() { + return Vector3.of(x, y, z); + } + + @Override + public void position(Vector3 position) { + x = position.getX(); + y = position.getY(); + z = position.getZ(); + } + + @Override + public void world(ServerWorld world) { + this.world = (TerraMinestomWorld) world; + } + + @Override + public ServerWorld world() { + return world; + } + + @Override + public Object getHandle() { + return this; + } + + public void spawn() { + int chunkX = (int) x >> 4; + int chunkZ = (int) z >> 4; + + if(!world.getHandle().isChunkLoaded(chunkX, chunkZ)) { + return; + } + + MinestomEntity.spawn(x, y, z, type, world); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntity.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntity.java new file mode 100644 index 000000000..c46a6a1d3 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntity.java @@ -0,0 +1,55 @@ +package com.dfsek.terra.minestom.entity; + +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; + +import com.dfsek.terra.minestom.MinestomAdapter; +import com.dfsek.terra.minestom.world.TerraMinestomWorld; + +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Entity; +import net.minestom.server.instance.Instance; + + +public class MinestomEntity implements com.dfsek.terra.api.entity.Entity { + private final Entity delegate; + private final TerraMinestomWorld world; + + public MinestomEntity(Entity delegate, TerraMinestomWorld world) { + this.delegate = delegate; + this.world = world; + } + + @Override + public Vector3 position() { + return MinestomAdapter.adapt(delegate.getPosition()); + } + + @Override + public void position(Vector3 position) { + delegate.teleport(MinestomAdapter.adapt(position)); + } + + @Override + public void world(ServerWorld world) { + delegate.setInstance(((TerraMinestomWorld) world).getHandle()); + } + + @Override + public ServerWorld world() { + return world; + } + + @Override + public Object getHandle() { + return delegate; + } + + public static MinestomEntity spawn(double x, double y, double z, EntityType type, TerraMinestomWorld world) { + Instance instance = world.getHandle(); + Entity entity = world.getEntityFactory().createEntity(((MinestomEntityType) type).getHandle()); + entity.setInstance(instance, new Pos(x, y, z)); + return new MinestomEntity(entity, world); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntityType.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntityType.java new file mode 100644 index 000000000..60fbac5d9 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/MinestomEntityType.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.minestom.entity; + + +import net.minestom.server.entity.EntityType; + + +public class MinestomEntityType implements com.dfsek.terra.api.entity.EntityType { + private final EntityType delegate; + + public MinestomEntityType(String id) { + delegate = EntityType.fromNamespaceId(id); + } + + @Override + public EntityType getHandle() { + return delegate; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index 628dcf990..d267d9900 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -11,6 +11,8 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; +import com.dfsek.terra.minestom.entity.DeferredMinestomEntity; + import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block.Setter; @@ -62,7 +64,10 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public Entity spawnEntity(double x, double y, double z, EntityType entityType) { - return null; + TerraMinestomWorld world = (TerraMinestomWorld) this.world; + DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world); + world.enqueueEntitySpawn(entity); + return entity; } @Override diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java index eb5731bb4..98429ab6d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomWorldHandle.java @@ -5,6 +5,8 @@ import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.minestom.block.MinestomBlockState; +import com.dfsek.terra.minestom.entity.MinestomEntityType; + import net.minestom.server.instance.block.Block; import org.jetbrains.annotations.NotNull; @@ -24,6 +26,6 @@ public class MinestomWorldHandle implements WorldHandle { @Override public @NotNull EntityType getEntity(@NotNull String id) { - return null; + return new MinestomEntityType(id); } } 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 aac669a32..5066b05cb 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 @@ -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.Chunk; @@ -13,10 +14,19 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.minestom.api.EntityFactory; +import com.dfsek.terra.minestom.block.MinestomBlockState; +import com.dfsek.terra.minestom.entity.DeferredMinestomEntity; +import com.dfsek.terra.minestom.entity.MinestomEntity; + import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; +import net.minestom.server.instance.block.Block; import net.minestom.server.world.DimensionType; +import java.util.ArrayList; +import java.util.HashMap; + public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final Instance instance; @@ -24,8 +34,9 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final long seed; private final DimensionType dimensionType; private final MinestomChunkGeneratorWrapper wrapper; + private final EntityFactory factory; - public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed) { + public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory) { this.instance = instance; this.pack = pack; this.seed = seed; @@ -36,6 +47,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { pack.getGeneratorProvider().newInstance(pack), this ); + this.factory = factory; instance.setGenerator(this.wrapper); } @@ -47,17 +59,17 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - + instance.setBlock(x, y, z, (Block) data.getHandle()); } @Override public Entity spawnEntity(double x, double y, double z, EntityType entityType) { - return null; + return MinestomEntity.spawn(x, y, z, entityType, this); } @Override public BlockState getBlockState(int x, int y, int z) { - return null; + return new MinestomBlockState(instance.getBlock(x, y, z)); } @Override @@ -96,11 +108,21 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { } @Override - public Object getHandle() { + public Instance getHandle() { return instance; } public DimensionType getDimensionType() { return dimensionType; } + + public EntityFactory getEntityFactory() { + return factory; + } + + public void enqueueEntitySpawn(DeferredMinestomEntity deferredMinestomEntity) { + int chunkX = deferredMinestomEntity.position().getBlockX() >> 4; + int chunkZ = deferredMinestomEntity.position().getBlockZ() >> 4; + instance.loadChunk(chunkX, chunkZ).thenAccept(chunk -> deferredMinestomEntity.spawn()); + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index 8b70b3a0f..5a018ef2d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -5,6 +5,8 @@ import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.minestom.MinestomPlatform; +import com.dfsek.terra.minestom.api.EntityFactory; +import com.dfsek.terra.minestom.entity.DefaultEntityFactory; import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; @@ -16,6 +18,7 @@ public class TerraMinestomWorldBuilder { private final Instance instance; private ConfigPack pack; private long seed = new Random().nextLong(); + private EntityFactory factory = new DefaultEntityFactory(); private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; } @@ -56,7 +59,12 @@ public class TerraMinestomWorldBuilder { return this; } + public TerraMinestomWorldBuilder entityFactory(EntityFactory factory) { + this.factory = factory; + return this; + } + public TerraMinestomWorld attach() { - return new TerraMinestomWorld(instance, pack, seed); + return new TerraMinestomWorld(instance, pack, seed, factory); } } From 23b846eca913f5714902fa3805fa31cde766c852 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 00:48:26 +0100 Subject: [PATCH 10/25] feat: get faster generation times --- .../terra/minestom/TerraMinestomExample.java | 17 +++++++++++++++-- .../minestom/chunk/GeneratedChunkCache.java | 12 +++++++++++- .../world/MinestomChunkGeneratorWrapper.java | 10 ++++------ .../minestom/world/MinestomProtoWorld.java | 9 +++++---- .../minestom/world/TerraMinestomWorld.java | 4 ++++ 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index c375d48fc..bec43cc80 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,5 +1,6 @@ package com.dfsek.terra.minestom; +import com.dfsek.terra.minestom.world.TerraMinestomWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; import net.minestom.server.MinecraftServer; @@ -12,6 +13,7 @@ import net.minestom.server.instance.Instance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; @@ -19,10 +21,12 @@ public class TerraMinestomExample { private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); private final MinecraftServer server = MinecraftServer.init(); private final Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + private TerraMinestomWorld world; public void attachTerra() { - TerraMinestomWorldBuilder.from(instance) + world = TerraMinestomWorldBuilder.from(instance) .defaultPack() + .seed(0) .attach(); } @@ -37,7 +41,7 @@ public class TerraMinestomExample { } public void preloadWorldAndMeasure() { - int radius = 6; + int radius = 12; int chunksLoading = (radius * 2 + 1) * (radius * 2 + 1); AtomicInteger chunksLeft = new AtomicInteger(chunksLoading); @@ -56,6 +60,8 @@ public class TerraMinestomExample { (end - start) / 1000000.0, chunksPerSecond ); + + world.displayStats(); } else if (left % 20 == 0) { 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() { logger.info("Starting server on port 25565"); server.start("localhost", 25565); @@ -84,6 +96,7 @@ public class TerraMinestomExample { TerraMinestomExample example = new TerraMinestomExample(); example.attachTerra(); example.preloadWorldAndMeasure(); + example.addScheduler(); example.addListeners(); example.bind(); } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java index 31eb2b7f9..c60feebcc 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java @@ -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.LoadingCache; +import com.github.benmanes.caffeine.cache.stats.CacheStats; import net.minestom.server.world.DimensionType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class GeneratedChunkCache { + private static final Logger log = LoggerFactory.getLogger(GeneratedChunkCache.class); private final LoadingCache, CachedChunk> cache; private final DimensionType dimensionType; private final ChunkGenerator generator; @@ -24,7 +28,8 @@ public class GeneratedChunkCache { this.world = world; this.biomeProvider = world.getBiomeProvider(); this.cache = Caffeine.newBuilder() - .maximumSize(32) + .maximumSize(128) + .recordStats() .build((Pair key) -> generateChunk(key.getLeft(), key.getRight())); } @@ -39,6 +44,11 @@ public class GeneratedChunkCache { 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) { return cache.get(Pair.of(x, z)); } 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 fd48e874f..061729c92 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 @@ -31,13 +31,7 @@ public class MinestomChunkGeneratorWrapper implements Generator { public void generate(@NotNull GenerationUnit unit) { Point start = unit.absoluteStart(); CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ()); - chunk.writeRelative(unit.modifier()); - - //if (start.chunkX() % 2 == 0 && start.chunkZ() % 2 == 0) { - //chunk.writeRelative(unit.modifier()); - //} - unit.fork(setter -> { MinestomProtoWorld protoWorld = new MinestomProtoWorld( cache, @@ -52,4 +46,8 @@ public class MinestomChunkGeneratorWrapper implements Generator { } }); } + + public void displayStats() { + cache.displayStats(); + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index d267d9900..b3cbb768d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -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.chunk.generation.ChunkGenerator; 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.entity.DeferredMinestomEntity; @@ -21,14 +22,14 @@ public class MinestomProtoWorld implements ProtoWorld { private final GeneratedChunkCache cache; private final int x; private final int z; - private final ServerWorld world; + private final TerraMinestomWorld world; private final Setter modifier; public MinestomProtoWorld( GeneratedChunkCache cache, int x, int z, - ServerWorld world, + TerraMinestomWorld world, Setter modifier ) { this.cache = cache; @@ -74,8 +75,8 @@ public class MinestomProtoWorld implements ProtoWorld { public BlockState getBlockState(int x, int y, int z) { int chunkX = x >> 4; int chunkZ = z >> 4; - return cache.at(chunkX, chunkZ) - .getBlock(x & 15, y, z & 15); + CachedChunk chunk = cache.at(chunkX, chunkZ); + return chunk.getBlock(x & 15, y, z & 15); } @Override 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 5066b05cb..671ad8e90 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 @@ -67,6 +67,10 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { return MinestomEntity.spawn(x, y, z, entityType, this); } + public void displayStats() { + wrapper.displayStats(); + } + @Override public BlockState getBlockState(int x, int y, int z) { return new MinestomBlockState(instance.getBlock(x, y, z)); From 627963836384be8fcdec42abbfa9560893855bf1 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 12:27:40 +0100 Subject: [PATCH 11/25] feat: implement platform biome --- .../terra/minestom/MinestomPlatform.java | 13 ++++++-- .../terra/minestom/biome/MinestomBiome.java | 17 ++++++++++ .../minestom/biome/MinestomBiomeLoader.java | 31 +++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiome.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java index 2cac94575..3e778039d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java @@ -5,12 +5,16 @@ import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.loader.type.TypeLoader; import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.minestom.biome.MinestomBiomeLoader; +import com.dfsek.terra.minestom.entity.MinestomEntityType; import com.dfsek.terra.minestom.item.MinestomItemHandle; import com.dfsek.terra.minestom.world.MinestomWorldHandle; @@ -33,7 +37,10 @@ public final class MinestomPlatform extends AbstractPlatform { @Override public void register(TypeRegistry registry) { super.register(registry); - registry.registerLoader(PlatformBiome.class, (TypeLoader) (annotatedType, o, configLoader, depthTracker) -> () -> o); + registry + .registerLoader(PlatformBiome.class, new MinestomBiomeLoader()) + .registerLoader(EntityType.class, (TypeLoader) (annotatedType, o, configLoader, depthTracker) -> new MinestomEntityType((String) o)) + .registerLoader(BlockState.class, (TypeLoader) (annotatedType, o, configLoader, depthTracker) -> worldHandle.createBlockState((String) o)); } @Override @@ -59,13 +66,13 @@ public final class MinestomPlatform extends AbstractPlatform { @Override public @NotNull File getDataFolder() { File file = new File("./terra/"); - if (!file.exists()) file.mkdirs(); + if(!file.exists()) file.mkdirs(); return file; } public static MinestomPlatform getInstance() { - if (INSTANCE == null) { + if(INSTANCE == null) { INSTANCE = new MinestomPlatform(); } return INSTANCE; diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiome.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiome.java new file mode 100644 index 000000000..a4c146359 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiome.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.minestom.biome; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + +import net.minestom.server.world.biome.Biome; + + +public class MinestomBiome implements PlatformBiome { + private final Biome biome; + + public MinestomBiome(Biome biome) { this.biome = biome; } + + @Override + public Biome getHandle() { + return biome; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java new file mode 100644 index 000000000..f74ba415e --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.minestom.biome; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.utils.NamespaceID; +import net.minestom.server.world.biome.Biome; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + + +public class MinestomBiomeLoader implements TypeLoader { + private final DynamicRegistry biomeRegistry = MinecraftServer.getBiomeRegistry(); + + @Override + public PlatformBiome load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader, + DepthTracker depthTracker) throws LoadException { + String id = (String) o; + NamespaceID biomeID = NamespaceID.from(id); + Biome biome = biomeRegistry.get(biomeID); + if (biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker); + return new MinestomBiome(biome); + } +} From 1d8a208d10a984cd1cf92e3f7e69fd8459feb40b Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 19:32:14 +0100 Subject: [PATCH 12/25] feat: implement platform enchantments --- .../minestom/item/MinestomEnchantment.java | 51 +++++++++++++ .../minestom/item/MinestomItemHandle.java | 14 +++- .../terra/minestom/item/MinestomItemMeta.java | 31 ++++++++ .../minestom/item/MinestomItemStack.java | 76 +++++++++++++++++++ .../terra/minestom/item/MinestomMaterial.java | 39 ++++++++++ 5 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomEnchantment.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemMeta.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomEnchantment.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomEnchantment.java new file mode 100644 index 000000000..0ef720b31 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomEnchantment.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.minestom.item; + +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.Enchantment; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.item.Material; +import net.minestom.server.utils.NamespaceID; + +import java.util.Objects; + + +public class MinestomEnchantment implements Enchantment { + private final net.minestom.server.item.enchant.Enchantment delegate; + private final String id; + + public MinestomEnchantment(net.minestom.server.item.enchant.Enchantment delegate) { + this.delegate = delegate; + id = Objects.requireNonNull(delegate.registry()).raw(); + } + + public MinestomEnchantment(String id) { + this.delegate = MinecraftServer.getEnchantmentRegistry().get(NamespaceID.from(id)); + this.id = id; + } + + @Override + public boolean canEnchantItem(ItemStack itemStack) { + return delegate.supportedItems().contains((Material) itemStack.getType().getHandle()); + } + + @Override + public boolean conflictsWith(Enchantment other) { + return delegate.exclusiveSet().contains(NamespaceID.from(((MinestomEnchantment) other).id)); + } + + @Override + public String getID() { + return id; + } + + @Override + public int getMaxLevel() { + return delegate.maxLevel(); + } + + @Override + public net.minestom.server.item.enchant.Enchantment getHandle() { + return delegate; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java index 65ddb1605..e80404ab9 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java @@ -4,22 +4,30 @@ import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.inventory.Item; import com.dfsek.terra.api.inventory.item.Enchantment; +import net.minestom.server.MinecraftServer; + import java.util.Set; +import java.util.stream.Collectors; public class MinestomItemHandle implements ItemHandle { @Override public Item createItem(String data) { - return null; + return new MinestomMaterial(data); } @Override public Enchantment getEnchantment(String id) { - return null; + return new MinestomEnchantment(id); } @Override public Set getEnchantments() { - return Set.of(); + return MinecraftServer + .getEnchantmentRegistry() + .values() + .stream() + .map(MinestomEnchantment::new) + .collect(Collectors.toSet()); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemMeta.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemMeta.java new file mode 100644 index 000000000..861a9549c --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemMeta.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.minestom.item; + +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; + +import java.util.HashMap; +import java.util.Map; + + +public class MinestomItemMeta implements ItemMeta { + private final HashMap enchantments; + + public MinestomItemMeta(HashMap enchantments) { + this.enchantments = enchantments; + } + + @Override + public void addEnchantment(Enchantment enchantment, int level) { + enchantments.put(enchantment, level); + } + + @Override + public Map getEnchantments() { + return enchantments; + } + + @Override + public Object getHandle() { + return enchantments; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java new file mode 100644 index 000000000..3ed760a57 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java @@ -0,0 +1,76 @@ +package com.dfsek.terra.minestom.item; + +import com.dfsek.terra.api.inventory.Item; + +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.item.ItemComponent; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.component.EnchantmentList; +import net.minestom.server.registry.DynamicRegistry; +import net.minestom.server.registry.DynamicRegistry.Key; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Objects; + + +public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStack { + private ItemStack base; + + public MinestomItemStack(net.minestom.server.item.@NotNull ItemStack base) { + this.base = base; + } + + @Override + public Object getHandle() { + return base; + } + + @Override + public int getAmount() { + return base.amount(); + } + + @Override + public void setAmount(int i) { + base = base.withAmount(i); + } + + @Override + public Item getType() { + return new MinestomMaterial(base.material()); + } + + @Override + public ItemMeta getItemMeta() { + HashMap enchantments = new HashMap<>(); + EnchantmentList enchantmentList = base.get(ItemComponent.ENCHANTMENTS); + if(enchantmentList != null) { + enchantmentList.enchantments().forEach((enchantmentKey, integer) -> { + enchantments.put(new MinestomEnchantment( + Objects.requireNonNull(MinecraftServer.getEnchantmentRegistry().get(enchantmentKey))), + integer + ); + }); + } + return new MinestomItemMeta(enchantments); + } + + @Override + public void setItemMeta(ItemMeta meta) { + HashMap, Integer> enchantments = new HashMap<>(); + DynamicRegistry registry = MinecraftServer.getEnchantmentRegistry(); + meta + .getEnchantments() + .forEach((key, value) -> { + MinestomEnchantment enchantment = (MinestomEnchantment) key; + enchantments.put(registry.getKey(enchantment.getHandle()), value); + }); + + EnchantmentList list = new EnchantmentList(enchantments); + base = base.with(ItemComponent.ENCHANTMENTS, list); + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java new file mode 100644 index 000000000..2bd1e6a97 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java @@ -0,0 +1,39 @@ +package com.dfsek.terra.minestom.item; + +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.ItemStack; + +import net.minestom.server.item.Material; + + +public class MinestomMaterial implements Item { + private final Material delegate; + + public MinestomMaterial(Material delegate) { + this.delegate = delegate; + } + + public MinestomMaterial(String id) { + this.delegate = Material.fromNamespaceId(id); + } + + @Override + public ItemStack newItemStack(int amount) { + return new MinestomItemStack( + net.minestom.server.item.ItemStack + .builder(delegate) + .amount(amount) + .build() + ); + } + + @Override + public double getMaxDurability() { + return 0; + } + + @Override + public Material getHandle() { + return delegate; + } +} From 4f668adb6794dfb7be3568140d800aca5b8a80ac Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 20:49:07 +0100 Subject: [PATCH 13/25] feat: add chunk filtering for debugging and remove feature caching Removed Feature caching since it was buggy asf --- .../terra/minestom/TerraMinestomExample.java | 66 +++++++++++++++++-- .../minestom/api/filter/ChunkFilter.java | 12 ++++ .../minestom/api/filter/EvenChunkFilter.java | 13 ++++ .../minestom/api/filter/NoFeaturesFilter.java | 13 ++++ .../minestom/api/filter/NoTerrainFilter.java | 13 ++++ .../api/filter/SpecificChunkFilter.java | 21 ++++++ .../terra/minestom/api/filter/XFilter.java | 17 +++++ .../terra/minestom/api/filter/ZFilter.java | 17 +++++ .../terra/minestom/chunk/CachedChunk.java | 7 +- .../world/MinestomChunkGeneratorWrapper.java | 33 +++++----- .../minestom/world/MinestomProtoWorld.java | 6 +- .../minestom/world/TerraMinestomWorld.java | 10 ++- .../world/TerraMinestomWorldBuilder.java | 10 ++- 13 files changed, 201 insertions(+), 37 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index bec43cc80..acc5abdfc 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,15 +1,26 @@ package com.dfsek.terra.minestom; +import com.dfsek.terra.minestom.api.filter.ChunkFilter; +import com.dfsek.terra.minestom.api.filter.EvenChunkFilter; +import com.dfsek.terra.minestom.api.filter.NoFeaturesFilter; +import com.dfsek.terra.minestom.api.filter.NoTerrainFilter; +import com.dfsek.terra.minestom.api.filter.SpecificChunkFilter; +import com.dfsek.terra.minestom.api.filter.XFilter; +import com.dfsek.terra.minestom.api.filter.ZFilter; import com.dfsek.terra.minestom.world.TerraMinestomWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; +import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.command.builder.Command; +import net.minestom.server.command.builder.arguments.ArgumentLiteral; +import net.minestom.server.command.builder.arguments.number.ArgumentInteger; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,20 +31,25 @@ import java.util.concurrent.atomic.AtomicInteger; public class TerraMinestomExample { private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); private final MinecraftServer server = MinecraftServer.init(); - private final Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + private Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); private TerraMinestomWorld world; - public void attachTerra() { + public void createNewInstance() { + instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + } + + public void attachTerra(ChunkFilter filter) { world = TerraMinestomWorldBuilder.from(instance) .defaultPack() - .seed(0) +// .seed(0) + .filtered(filter) .attach(); } private void sendProgressBar(int current, int max) { - String left = "#".repeat((int) ((((float) current)/max) * 20)); + String left = "#".repeat((int) ((((float) current) / max) * 20)); String right = ".".repeat(20 - left.length()); - int percent = (int) (((float) current)/max * 100); + int percent = (int) (((float) current) / max * 100); String percentString = percent + "%"; percentString = " ".repeat(4 - percentString.length()) + percentString; String message = percentString + " |" + left + right + "| " + current + "/" + max; @@ -62,7 +78,7 @@ public class TerraMinestomExample { ); world.displayStats(); - } else if (left % 20 == 0) { + } else if(left % 20 == 0) { sendProgressBar(chunksLoading - left, chunksLoading); } }); @@ -87,6 +103,10 @@ public class TerraMinestomExample { .schedule(); } + public void addCommands() { + MinecraftServer.getCommandManager().register(new RegenerateCommand()); + } + public void bind() { logger.info("Starting server on port 25565"); server.start("localhost", 25565); @@ -94,10 +114,42 @@ public class TerraMinestomExample { public static void main(String[] args) { TerraMinestomExample example = new TerraMinestomExample(); - example.attachTerra(); + example.attachTerra(null); example.preloadWorldAndMeasure(); example.addScheduler(); example.addListeners(); + example.addCommands(); example.bind(); } + + public class RegenerateCommand extends Command { + public RegenerateCommand() { + super("regenerate"); + + ArgumentInteger cx = new ArgumentInteger("cx"); + ArgumentInteger cz = new ArgumentInteger("cz"); + + setDefaultExecutor((sender, context) -> regenerate(null)); + addSyntax((sender, context) -> regenerate(new NoFeaturesFilter()), new ArgumentLiteral("noFeatures")); + addSyntax((sender, context) -> regenerate(new NoTerrainFilter()), new ArgumentLiteral("noTerrain")); + addSyntax((sender, context) -> regenerate(new EvenChunkFilter()), new ArgumentLiteral("evenChunks")); + addSyntax((sender, context) -> regenerate(new SpecificChunkFilter(context.get(cx), context.get(cz))), new ArgumentLiteral("chunk"), cx, cz); + addSyntax((sender, context) -> regenerate(new XFilter(context.get(cx))), new ArgumentLiteral("x"), cx); + addSyntax((sender, context) -> regenerate(new ZFilter(context.get(cz))), new ArgumentLiteral("z"), cz); + } + + private void regenerate(@Nullable ChunkFilter filter) { + if (filter == null) { + instance.sendMessage(Component.text("Regenerating world without filter ")); + } else { + instance.sendMessage(Component.text("Regenerating world with filter " + filter.getClass().getSimpleName())); + } + createNewInstance(); + attachTerra(filter); + preloadWorldAndMeasure(); + MinecraftServer.getConnectionManager().getOnlinePlayers().forEach(player -> + player.setInstance(instance, new Pos(0, 100, 0)) + ); + } + } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java new file mode 100644 index 000000000..a72ebcc6d --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.minestom.api.filter; + +/** + * This interface defines a filter for determining whether terrain and features + * should be placed during chunk generation. Implementations of this interface + * can apply custom logic to selectively control terrain and feature placement + * in specific chunks for debugging purposes. + */ +public interface ChunkFilter { + boolean shouldPlaceTerrain(int x, int z); + boolean shouldPlaceFeatures(int x, int z); +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java new file mode 100644 index 000000000..f97507ed1 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.minestom.api.filter; + +public class EvenChunkFilter implements ChunkFilter { + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return x % 2 == 0 && z % 2 == 0; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return x % 2 == 0 && z % 2 == 0; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java new file mode 100644 index 000000000..dbbdeb94d --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.minestom.api.filter; + +public class NoFeaturesFilter implements ChunkFilter { + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return true; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return false; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java new file mode 100644 index 000000000..671c746bd --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.minestom.api.filter; + +public class NoTerrainFilter implements ChunkFilter { + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return false; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return true; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java new file mode 100644 index 000000000..cd1670188 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.minestom.api.filter; + +public class SpecificChunkFilter implements ChunkFilter { + private final int x; + private final int z; + + public SpecificChunkFilter(int x, int z) { + this.x = x; + this.z = z; + } + + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return this.x == x && this.z == z; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return this.x == x && this.z == z; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java new file mode 100644 index 000000000..c282bc2a3 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.minestom.api.filter; + +public class XFilter implements ChunkFilter { + private final int x; + + public XFilter(int x) { this.x = x; } + + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return this.x == x; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return this.x == x; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java new file mode 100644 index 000000000..39dfb054e --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.minestom.api.filter; + +public class ZFilter implements ChunkFilter { + private final int z; + + public ZFilter(int z) { this.z = z; } + + @Override + public boolean shouldPlaceTerrain(int x, int z) { + return this.z == z; + } + + @Override + public boolean shouldPlaceFeatures(int x, int z) { + return this.z == z; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java index 5a57f9830..ed9ad8622 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/CachedChunk.java @@ -5,6 +5,7 @@ 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; @@ -20,9 +21,9 @@ public class CachedChunk implements ProtoChunk { 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++) { + 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; } } 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 061729c92..9daf2b60f 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 @@ -3,6 +3,7 @@ package com.dfsek.terra.minestom.world; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.chunk.CachedChunk; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; @@ -16,10 +17,12 @@ public class MinestomChunkGeneratorWrapper implements Generator { private final GeneratedChunkCache cache; private final ChunkGenerator generator; private final TerraMinestomWorld world; + private final ChunkFilter filter; - public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world) { + public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ChunkFilter filter) { this.generator = generator; this.world = world; + this.filter = filter; this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world); } @@ -30,21 +33,21 @@ public class MinestomChunkGeneratorWrapper implements Generator { @Override public void generate(@NotNull GenerationUnit unit) { Point start = unit.absoluteStart(); - CachedChunk chunk = cache.at(start.chunkX(), start.chunkZ()); - chunk.writeRelative(unit.modifier()); - unit.fork(setter -> { - MinestomProtoWorld protoWorld = new MinestomProtoWorld( - cache, - start.chunkX(), - start.chunkZ(), - world, - setter - ); + int x = start.chunkX(); + int z = start.chunkZ(); + CachedChunk chunk = cache.at(x, z); + if(filter == null || filter.shouldPlaceTerrain(x, z)) + chunk.writeRelative(unit.modifier()); - for(GenerationStage stage : world.getPack().getStages()) { - stage.populate(protoWorld); - } - }); + if(filter == null || filter.shouldPlaceFeatures(x, z)) { + unit.fork(setter -> { + MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter); + + for(GenerationStage stage : world.getPack().getStages()) { + stage.populate(protoWorld); + } + }); + } } public void displayStats() { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index b3cbb768d..61d1482f6 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -56,16 +56,12 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - int cx = x >> 4; - int cz = y >> 4; modifier.setBlock(x, y, z, (Block) data.getHandle()); - cache.at(cx, cz) - .setBlock(x & 15, y, z & 15, data); } @Override public Entity spawnEntity(double x, double y, double z, EntityType entityType) { - TerraMinestomWorld world = (TerraMinestomWorld) this.world; + TerraMinestomWorld world = this.world; DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world); world.enqueueEntitySpawn(entity); return entity; 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 671ad8e90..847b40eac 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 @@ -5,7 +5,6 @@ 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.Chunk; @@ -16,6 +15,7 @@ import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.minestom.api.EntityFactory; import com.dfsek.terra.minestom.block.MinestomBlockState; +import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.entity.DeferredMinestomEntity; import com.dfsek.terra.minestom.entity.MinestomEntity; @@ -24,9 +24,6 @@ import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; import net.minestom.server.world.DimensionType; -import java.util.ArrayList; -import java.util.HashMap; - public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final Instance instance; @@ -36,7 +33,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final MinestomChunkGeneratorWrapper wrapper; private final EntityFactory factory; - public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory) { + public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory, ChunkFilter filter) { this.instance = instance; this.pack = pack; this.seed = seed; @@ -45,7 +42,8 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { this.wrapper = new MinestomChunkGeneratorWrapper( pack.getGeneratorProvider().newInstance(pack), - this + this, + filter ); this.factory = factory; diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index 5a018ef2d..eba7621a4 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -6,9 +6,11 @@ import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.minestom.MinestomPlatform; import com.dfsek.terra.minestom.api.EntityFactory; +import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.entity.DefaultEntityFactory; import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; +import org.jetbrains.annotations.Nullable; import java.util.Random; import java.util.function.Function; @@ -19,6 +21,7 @@ public class TerraMinestomWorldBuilder { private ConfigPack pack; private long seed = new Random().nextLong(); private EntityFactory factory = new DefaultEntityFactory(); + private ChunkFilter filter; private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; } @@ -64,7 +67,12 @@ public class TerraMinestomWorldBuilder { return this; } + public TerraMinestomWorldBuilder filtered(@Nullable ChunkFilter filter) { + this.filter = filter; + return this; + } + public TerraMinestomWorld attach() { - return new TerraMinestomWorld(instance, pack, seed, factory); + return new TerraMinestomWorld(instance, pack, seed, factory, filter); } } From cb2841ed4f5a5c841f80fc57e8153c202170620b Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 20:54:56 +0100 Subject: [PATCH 14/25] fix: Adjust progress bar update interval to every 60 ticks. --- .../java/com/dfsek/terra/minestom/TerraMinestomExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index acc5abdfc..5f3aeda91 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -78,7 +78,7 @@ public class TerraMinestomExample { ); world.displayStats(); - } else if(left % 20 == 0) { + } else if(left % 60 == 0) { sendProgressBar(chunksLoading - left, chunksLoading); } }); From ff153ddc21ef64f65e3c6ff83a281a0c39c7629f Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Thu, 2 Jan 2025 23:22:44 +0100 Subject: [PATCH 15/25] feat: allow external block entity implementations --- .../minestom/api/BlockEntityFactory.java | 16 ++++++++++ .../block/DefaultBlockEntityFactory.java | 14 +++++++++ .../entity/DeferredMinestomEntity.java | 6 ++++ .../minestom/world/MinestomProtoWorld.java | 4 +-- .../minestom/world/TerraMinestomWorld.java | 31 +++++++++++++------ .../world/TerraMinestomWorldBuilder.java | 14 +++++++-- 6 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/BlockEntityFactory.java create mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/DefaultBlockEntityFactory.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/BlockEntityFactory.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/BlockEntityFactory.java new file mode 100644 index 000000000..c5fd33ca1 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/BlockEntityFactory.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.minestom.api; + +import com.dfsek.terra.api.block.entity.BlockEntity; + +import net.minestom.server.coordinate.BlockVec; +import org.jetbrains.annotations.Nullable; + + +/** + * Represents a factory interface for creating instances of BlockEntity + * at a specified BlockVec position. This is not implemented directly because + * Minestom does not define a way to build block entities out of the box. + */ +public interface BlockEntityFactory { + @Nullable BlockEntity createBlockEntity(BlockVec position); +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/DefaultBlockEntityFactory.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/DefaultBlockEntityFactory.java new file mode 100644 index 000000000..dbcbf2833 --- /dev/null +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/DefaultBlockEntityFactory.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.minestom.block; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.minestom.api.BlockEntityFactory; + +import net.minestom.server.coordinate.BlockVec; + + +public class DefaultBlockEntityFactory implements BlockEntityFactory { + @Override + public BlockEntity createBlockEntity(BlockVec position) { + return null; + } +} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java index 6dfdf5b52..4a053ec2d 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/entity/DeferredMinestomEntity.java @@ -6,6 +6,8 @@ import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorld; +import net.minestom.server.coordinate.Pos; + public class DeferredMinestomEntity implements Entity { private final EntityType type; @@ -27,6 +29,10 @@ public class DeferredMinestomEntity implements Entity { return Vector3.of(x, y, z); } + public Pos pos() { + return new Pos(x, y, z); + } + @Override public void position(Vector3 position) { x = position.getX(); diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index 61d1482f6..e4cab993f 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -63,7 +63,7 @@ public class MinestomProtoWorld implements ProtoWorld { public Entity spawnEntity(double x, double y, double z, EntityType entityType) { TerraMinestomWorld world = this.world; DeferredMinestomEntity entity = new DeferredMinestomEntity(x, y, z, entityType, world); - world.enqueueEntitySpawn(entity); + world.enqueue(entity.pos(), (chunk) -> entity.spawn()); return entity; } @@ -77,7 +77,7 @@ public class MinestomProtoWorld implements ProtoWorld { @Override public BlockEntity getBlockEntity(int x, int y, int z) { - return null; + return world.getBlockEntity(x, y, z); } @Override 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 847b40eac..e5cf73410 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 @@ -13,17 +13,21 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.minestom.api.BlockEntityFactory; import com.dfsek.terra.minestom.api.EntityFactory; import com.dfsek.terra.minestom.block.MinestomBlockState; import com.dfsek.terra.minestom.api.filter.ChunkFilter; -import com.dfsek.terra.minestom.entity.DeferredMinestomEntity; import com.dfsek.terra.minestom.entity.MinestomEntity; import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.BlockVec; +import net.minestom.server.coordinate.Point; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; import net.minestom.server.world.DimensionType; +import java.util.function.Consumer; + public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final Instance instance; @@ -31,21 +35,30 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { private final long seed; private final DimensionType dimensionType; private final MinestomChunkGeneratorWrapper wrapper; - private final EntityFactory factory; + private final EntityFactory entityFactory; + private final BlockEntityFactory blockEntityFactory; - public TerraMinestomWorld(Instance instance, ConfigPack pack, long seed, EntityFactory factory, ChunkFilter filter) { + public TerraMinestomWorld( + Instance instance, + ConfigPack pack, + long seed, + EntityFactory entityFactory, + ChunkFilter filter, + BlockEntityFactory blockEntityFactory + ) { this.instance = instance; this.pack = pack; this.seed = seed; this.dimensionType = MinecraftServer.getDimensionTypeRegistry().get(instance.getDimensionType()); + this.blockEntityFactory = blockEntityFactory; this.wrapper = new MinestomChunkGeneratorWrapper( pack.getGeneratorProvider().newInstance(pack), this, filter ); - this.factory = factory; + this.entityFactory = entityFactory; instance.setGenerator(this.wrapper); } @@ -76,7 +89,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { @Override public BlockEntity getBlockEntity(int x, int y, int z) { - return null; + return blockEntityFactory.createBlockEntity(new BlockVec(x, y, z)); } @Override @@ -119,12 +132,10 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { } public EntityFactory getEntityFactory() { - return factory; + return entityFactory; } - public void enqueueEntitySpawn(DeferredMinestomEntity deferredMinestomEntity) { - int chunkX = deferredMinestomEntity.position().getBlockX() >> 4; - int chunkZ = deferredMinestomEntity.position().getBlockZ() >> 4; - instance.loadChunk(chunkX, chunkZ).thenAccept(chunk -> deferredMinestomEntity.spawn()); + public void enqueue(Point position, Consumer action) { + instance.loadChunk(position.chunkX(), position.chunkZ()).thenAccept(action); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index eba7621a4..86ff34c41 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -5,8 +5,10 @@ import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.minestom.MinestomPlatform; +import com.dfsek.terra.minestom.api.BlockEntityFactory; import com.dfsek.terra.minestom.api.EntityFactory; import com.dfsek.terra.minestom.api.filter.ChunkFilter; +import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory; import com.dfsek.terra.minestom.entity.DefaultEntityFactory; import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; @@ -20,8 +22,9 @@ public class TerraMinestomWorldBuilder { private final Instance instance; private ConfigPack pack; private long seed = new Random().nextLong(); - private EntityFactory factory = new DefaultEntityFactory(); + private EntityFactory entityFactory = new DefaultEntityFactory(); private ChunkFilter filter; + private BlockEntityFactory blockEntityFactory = new DefaultBlockEntityFactory(); private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; } @@ -63,7 +66,12 @@ public class TerraMinestomWorldBuilder { } public TerraMinestomWorldBuilder entityFactory(EntityFactory factory) { - this.factory = factory; + this.entityFactory = factory; + return this; + } + + public TerraMinestomWorldBuilder blockEntityFactory(BlockEntityFactory factory) { + this.blockEntityFactory = factory; return this; } @@ -73,6 +81,6 @@ public class TerraMinestomWorldBuilder { } public TerraMinestomWorld attach() { - return new TerraMinestomWorld(instance, pack, seed, factory, filter); + return new TerraMinestomWorld(instance, pack, seed, entityFactory, filter, blockEntityFactory); } } From c848c33bc0cb462b365203137dd599e7bd9f1956 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Fri, 3 Jan 2025 17:28:47 +0100 Subject: [PATCH 16/25] fix: add lighting engine to test server --- .../java/com/dfsek/terra/minestom/TerraMinestomExample.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 5f3aeda91..159a9562a 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -20,6 +20,7 @@ import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; +import net.minestom.server.instance.LightingChunk; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,11 +32,12 @@ import java.util.concurrent.atomic.AtomicInteger; public class TerraMinestomExample { private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); private final MinecraftServer server = MinecraftServer.init(); - private Instance instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + private Instance instance; private TerraMinestomWorld world; public void createNewInstance() { instance = MinecraftServer.getInstanceManager().createInstanceContainer(); + instance.setChunkSupplier(LightingChunk::new); } public void attachTerra(ChunkFilter filter) { @@ -114,6 +116,7 @@ public class TerraMinestomExample { public static void main(String[] args) { TerraMinestomExample example = new TerraMinestomExample(); + example.createNewInstance(); example.attachTerra(null); example.preloadWorldAndMeasure(); example.addScheduler(); From 5ba5d6efdd28937e842050f53939a8bf521b5dfe Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Fri, 3 Jan 2025 22:19:08 +0100 Subject: [PATCH 17/25] revert: block type implementation hint --- .../api/src/main/java/com/dfsek/terra/api/block/BlockType.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java index 5db6aa3d7..471fc6f43 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java @@ -13,9 +13,6 @@ import com.dfsek.terra.api.block.state.BlockState; /** * Represents a type of block - *

- * Important! You need to implement a proper equals() and hashCode() here in - * your platform implementation for surface decorations to show up */ public interface BlockType extends Handle { /** From 35bdc99873f03bbb58151aa2c0225ad310b94ccb Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Fri, 3 Jan 2025 23:52:31 +0100 Subject: [PATCH 18/25] build: make available via maven repo --- .../src/main/kotlin/DistributionConfig.kt | 51 ++++++++++++------- platforms/minestom/build.gradle.kts | 4 ++ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt index a31588a51..72a4146f6 100644 --- a/buildSrc/src/main/kotlin/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -4,9 +4,11 @@ import java.io.File import java.io.FileWriter import java.net.URL import java.nio.file.FileSystems +import java.nio.file.Path import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.plugins.BasePluginExtension +import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.extra @@ -19,6 +21,25 @@ import kotlin.io.path.createDirectories import kotlin.io.path.createFile import kotlin.io.path.exists +private fun Project.installAddonsInto(dest: Path) { + FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs -> + forSubProjects(":common:addons") { + val jar = getJarTask() + + logger.info("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB") + + val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" + val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}") + + if (!addonPath.exists()) { + addonPath.parent.createDirectories() + addonPath.createFile() + jar.archiveFile.get().asFile.toPath().copyTo(addonPath, overwrite = true) + } + + } + } +} fun Project.configureDistribution() { apply(plugin = "com.gradleup.shadow") @@ -48,25 +69,17 @@ fun Project.configureDistribution() { doLast { // https://github.com/johnrengelman/shadow/issues/111 val dest = tasks.named("shadowJar").get().archiveFile.get().path - - - FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs -> - forSubProjects(":common:addons") { - val jar = getJarTask() - - logger.info("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB") - - val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" - val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}") - - if (!addonPath.exists()) { - addonPath.parent.createDirectories() - addonPath.createFile() - jar.archiveFile.get().asFile.toPath().copyTo(addonPath, overwrite = true) - } - - } - } + installAddonsInto(dest) + } + } + + tasks.create("installAddonsIntoDefaultJar") { + group = "terra" + dependsOn(compileAddons) + + doLast { + val dest = tasks.named("jar").get().archiveFile.get().path + installAddonsInto(dest) } } diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts index b1fb58dfd..b0732811c 100644 --- a/platforms/minestom/build.gradle.kts +++ b/platforms/minestom/build.gradle.kts @@ -26,6 +26,10 @@ application { mainClass.set(javaMainClass) } +tasks.named("jar") { + finalizedBy("installAddonsIntoDefaultJar") +} + tasks.getByName("run").setProperty("workingDir", file("./run")) addonDir(project.file("./run/terra/addons"), tasks.named("run").get()) From 7711e67999c4835c435c03e18b6050ccee56ab0e Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 4 Jan 2025 00:08:14 +0100 Subject: [PATCH 19/25] feat: support reload --- .../terra/minestom/MinestomPlatform.java | 21 ++++++++++- .../terra/minestom/TerraMinestomExample.java | 37 +++---------------- .../minestom/api/filter/ChunkFilter.java | 12 ------ .../minestom/api/filter/EvenChunkFilter.java | 13 ------- .../minestom/api/filter/NoFeaturesFilter.java | 13 ------- .../minestom/api/filter/NoTerrainFilter.java | 13 ------- .../api/filter/SpecificChunkFilter.java | 21 ----------- .../terra/minestom/api/filter/XFilter.java | 17 --------- .../terra/minestom/api/filter/ZFilter.java | 17 --------- .../world/MinestomChunkGeneratorWrapper.java | 36 ++++++++++-------- .../minestom/world/TerraMinestomWorld.java | 4 +- .../world/TerraMinestomWorldBuilder.java | 10 +---- 12 files changed, 49 insertions(+), 165 deletions(-) delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java delete mode 100644 platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java index 3e778039d..e85edbee1 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java @@ -17,14 +17,20 @@ import com.dfsek.terra.minestom.biome.MinestomBiomeLoader; import com.dfsek.terra.minestom.entity.MinestomEntityType; import com.dfsek.terra.minestom.item.MinestomItemHandle; +import com.dfsek.terra.minestom.world.MinestomChunkGeneratorWrapper; import com.dfsek.terra.minestom.world.MinestomWorldHandle; +import net.minestom.server.MinecraftServer; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; +import java.util.ArrayList; public final class MinestomPlatform extends AbstractPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(MinestomPlatform.class); private static MinestomPlatform INSTANCE = null; private final MinestomWorldHandle worldHandle = new MinestomWorldHandle(); private final MinestomItemHandle itemHandle = new MinestomItemHandle(); @@ -45,7 +51,20 @@ public final class MinestomPlatform extends AbstractPlatform { @Override public boolean reload() { - return false; + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + MinecraftServer.getInstanceManager().getInstances().forEach(world -> { + if(world.generator() instanceof MinestomChunkGeneratorWrapper wrapper) { + getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> { + wrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for instance {}", world.getUniqueId()); + }); + } + }); + + return succeed; } @Override diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 159a9562a..20dd10bbd 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,19 +1,11 @@ package com.dfsek.terra.minestom; -import com.dfsek.terra.minestom.api.filter.ChunkFilter; -import com.dfsek.terra.minestom.api.filter.EvenChunkFilter; -import com.dfsek.terra.minestom.api.filter.NoFeaturesFilter; -import com.dfsek.terra.minestom.api.filter.NoTerrainFilter; -import com.dfsek.terra.minestom.api.filter.SpecificChunkFilter; -import com.dfsek.terra.minestom.api.filter.XFilter; -import com.dfsek.terra.minestom.api.filter.ZFilter; import com.dfsek.terra.minestom.world.TerraMinestomWorld; import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.command.builder.Command; -import net.minestom.server.command.builder.arguments.ArgumentLiteral; import net.minestom.server.command.builder.arguments.number.ArgumentInteger; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; @@ -21,7 +13,6 @@ import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.minestom.server.event.player.PlayerSpawnEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.LightingChunk; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,11 +31,9 @@ public class TerraMinestomExample { instance.setChunkSupplier(LightingChunk::new); } - public void attachTerra(ChunkFilter filter) { + public void attachTerra() { world = TerraMinestomWorldBuilder.from(instance) .defaultPack() -// .seed(0) - .filtered(filter) .attach(); } @@ -117,7 +106,7 @@ public class TerraMinestomExample { public static void main(String[] args) { TerraMinestomExample example = new TerraMinestomExample(); example.createNewInstance(); - example.attachTerra(null); + example.attachTerra(); example.preloadWorldAndMeasure(); example.addScheduler(); example.addListeners(); @@ -128,27 +117,13 @@ public class TerraMinestomExample { public class RegenerateCommand extends Command { public RegenerateCommand() { super("regenerate"); - - ArgumentInteger cx = new ArgumentInteger("cx"); - ArgumentInteger cz = new ArgumentInteger("cz"); - - setDefaultExecutor((sender, context) -> regenerate(null)); - addSyntax((sender, context) -> regenerate(new NoFeaturesFilter()), new ArgumentLiteral("noFeatures")); - addSyntax((sender, context) -> regenerate(new NoTerrainFilter()), new ArgumentLiteral("noTerrain")); - addSyntax((sender, context) -> regenerate(new EvenChunkFilter()), new ArgumentLiteral("evenChunks")); - addSyntax((sender, context) -> regenerate(new SpecificChunkFilter(context.get(cx), context.get(cz))), new ArgumentLiteral("chunk"), cx, cz); - addSyntax((sender, context) -> regenerate(new XFilter(context.get(cx))), new ArgumentLiteral("x"), cx); - addSyntax((sender, context) -> regenerate(new ZFilter(context.get(cz))), new ArgumentLiteral("z"), cz); + setDefaultExecutor((sender, context) -> regenerate()); } - private void regenerate(@Nullable ChunkFilter filter) { - if (filter == null) { - instance.sendMessage(Component.text("Regenerating world without filter ")); - } else { - instance.sendMessage(Component.text("Regenerating world with filter " + filter.getClass().getSimpleName())); - } + private void regenerate() { + instance.sendMessage(Component.text("Regenerating world")); createNewInstance(); - attachTerra(filter); + attachTerra(); preloadWorldAndMeasure(); MinecraftServer.getConnectionManager().getOnlinePlayers().forEach(player -> player.setInstance(instance, new Pos(0, 100, 0)) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java deleted file mode 100644 index a72ebcc6d..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ChunkFilter.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -/** - * This interface defines a filter for determining whether terrain and features - * should be placed during chunk generation. Implementations of this interface - * can apply custom logic to selectively control terrain and feature placement - * in specific chunks for debugging purposes. - */ -public interface ChunkFilter { - boolean shouldPlaceTerrain(int x, int z); - boolean shouldPlaceFeatures(int x, int z); -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java deleted file mode 100644 index f97507ed1..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/EvenChunkFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class EvenChunkFilter implements ChunkFilter { - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return x % 2 == 0 && z % 2 == 0; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return x % 2 == 0 && z % 2 == 0; - } -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java deleted file mode 100644 index dbbdeb94d..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoFeaturesFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class NoFeaturesFilter implements ChunkFilter { - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return true; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return false; - } -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java deleted file mode 100644 index 671c746bd..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/NoTerrainFilter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class NoTerrainFilter implements ChunkFilter { - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return false; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return true; - } -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java deleted file mode 100644 index cd1670188..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/SpecificChunkFilter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class SpecificChunkFilter implements ChunkFilter { - private final int x; - private final int z; - - public SpecificChunkFilter(int x, int z) { - this.x = x; - this.z = z; - } - - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return this.x == x && this.z == z; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return this.x == x && this.z == z; - } -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java deleted file mode 100644 index c282bc2a3..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/XFilter.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class XFilter implements ChunkFilter { - private final int x; - - public XFilter(int x) { this.x = x; } - - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return this.x == x; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return this.x == x; - } -} diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java deleted file mode 100644 index 39dfb054e..000000000 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/api/filter/ZFilter.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.minestom.api.filter; - -public class ZFilter implements ChunkFilter { - private final int z; - - public ZFilter(int z) { this.z = z; } - - @Override - public boolean shouldPlaceTerrain(int x, int z) { - return this.z == z; - } - - @Override - public boolean shouldPlaceFeatures(int x, int z) { - return this.z == z; - } -} 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 9daf2b60f..5fbe9da90 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,9 @@ package com.dfsek.terra.minestom.world; +import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; -import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.chunk.CachedChunk; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; @@ -15,14 +15,14 @@ import org.jetbrains.annotations.NotNull; public class MinestomChunkGeneratorWrapper implements Generator { private final GeneratedChunkCache cache; - private final ChunkGenerator generator; + private ChunkGenerator generator; private final TerraMinestomWorld world; - private final ChunkFilter filter; + private ConfigPack pack; - public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ChunkFilter filter) { + public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack) { this.generator = generator; this.world = world; - this.filter = filter; + this.pack = pack; this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world); } @@ -36,18 +36,24 @@ public class MinestomChunkGeneratorWrapper implements Generator { int x = start.chunkX(); int z = start.chunkZ(); CachedChunk chunk = cache.at(x, z); - if(filter == null || filter.shouldPlaceTerrain(x, z)) - chunk.writeRelative(unit.modifier()); + chunk.writeRelative(unit.modifier()); - if(filter == null || filter.shouldPlaceFeatures(x, z)) { - unit.fork(setter -> { - MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter); + unit.fork(setter -> { + MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter); - for(GenerationStage stage : world.getPack().getStages()) { - stage.populate(protoWorld); - } - }); - } + for(GenerationStage stage : world.getPack().getStages()) { + stage.populate(protoWorld); + } + }); + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + this.generator = pack.getGeneratorProvider().newInstance(pack); } public void displayStats() { 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 e5cf73410..0cce989cf 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 @@ -16,7 +16,6 @@ import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.minestom.api.BlockEntityFactory; import com.dfsek.terra.minestom.api.EntityFactory; import com.dfsek.terra.minestom.block.MinestomBlockState; -import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.entity.MinestomEntity; import net.minestom.server.MinecraftServer; @@ -43,7 +42,6 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { ConfigPack pack, long seed, EntityFactory entityFactory, - ChunkFilter filter, BlockEntityFactory blockEntityFactory ) { this.instance = instance; @@ -56,7 +54,7 @@ public final class TerraMinestomWorld implements ServerWorld, WorldProperties { this.wrapper = new MinestomChunkGeneratorWrapper( pack.getGeneratorProvider().newInstance(pack), this, - filter + pack ); this.entityFactory = entityFactory; diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index 86ff34c41..7d04d6c9c 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -7,12 +7,10 @@ import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.minestom.MinestomPlatform; import com.dfsek.terra.minestom.api.BlockEntityFactory; import com.dfsek.terra.minestom.api.EntityFactory; -import com.dfsek.terra.minestom.api.filter.ChunkFilter; import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory; import com.dfsek.terra.minestom.entity.DefaultEntityFactory; import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; -import org.jetbrains.annotations.Nullable; import java.util.Random; import java.util.function.Function; @@ -23,7 +21,6 @@ public class TerraMinestomWorldBuilder { private ConfigPack pack; private long seed = new Random().nextLong(); private EntityFactory entityFactory = new DefaultEntityFactory(); - private ChunkFilter filter; private BlockEntityFactory blockEntityFactory = new DefaultBlockEntityFactory(); private TerraMinestomWorldBuilder(Instance instance) { this.instance = instance; } @@ -75,12 +72,7 @@ public class TerraMinestomWorldBuilder { return this; } - public TerraMinestomWorldBuilder filtered(@Nullable ChunkFilter filter) { - this.filter = filter; - return this; - } - public TerraMinestomWorld attach() { - return new TerraMinestomWorld(instance, pack, seed, entityFactory, filter, blockEntityFactory); + return new TerraMinestomWorld(instance, pack, seed, entityFactory, blockEntityFactory); } } From 992ae592fdce5519b9886b7ba4312d93a90b69a4 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 4 Jan 2025 00:14:32 +0100 Subject: [PATCH 20/25] fix: Implement GeneratorWrapper interface in Minestom wrapper --- .../minestom/world/MinestomChunkGeneratorWrapper.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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 5fbe9da90..81529db48 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 @@ -4,6 +4,7 @@ import com.dfsek.terra.api.config.ConfigPack; 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.chunk.CachedChunk; import com.dfsek.terra.minestom.chunk.GeneratedChunkCache; @@ -13,7 +14,7 @@ import net.minestom.server.instance.generator.Generator; import org.jetbrains.annotations.NotNull; -public class MinestomChunkGeneratorWrapper implements Generator { +public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrapper { private final GeneratedChunkCache cache; private ChunkGenerator generator; private final TerraMinestomWorld world; @@ -59,4 +60,9 @@ public class MinestomChunkGeneratorWrapper implements Generator { public void displayStats() { cache.displayStats(); } + + @Override + public ChunkGenerator getHandle() { + return generator; + } } From d0bc006faa77397df61f98a8fb3b6a80860d6c90 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 4 Jan 2025 20:42:54 +0100 Subject: [PATCH 21/25] chore: reformat --- .../terra/minestom/MinestomPlatform.java | 7 ------ .../minestom/biome/MinestomBiomeLoader.java | 2 +- .../minestom/block/MinestomBlockState.java | 22 +++++++------------ .../minestom/block/MinestomBlockType.java | 2 +- .../minestom/chunk/GeneratedChunkCache.java | 16 +++++--------- .../minestom/chunk/TerraMinestomChunk.java | 1 + .../minestom/item/MinestomItemHandle.java | 7 +----- .../minestom/item/MinestomItemStack.java | 16 +++++--------- .../terra/minestom/item/MinestomMaterial.java | 7 +----- .../minestom/world/MinestomProtoWorld.java | 8 +------ .../minestom/world/TerraMinestomWorld.java | 15 +++---------- .../world/TerraMinestomWorldBuilder.java | 7 ++---- 12 files changed, 30 insertions(+), 80 deletions(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java index e85edbee1..5dd149133 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java @@ -1,32 +1,25 @@ package com.dfsek.terra.minestom; import com.dfsek.tectonic.api.TypeRegistry; - import com.dfsek.tectonic.api.loader.type.TypeLoader; - import com.dfsek.terra.AbstractPlatform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.WorldHandle; - import com.dfsek.terra.api.world.biome.PlatformBiome; - import com.dfsek.terra.minestom.biome.MinestomBiomeLoader; import com.dfsek.terra.minestom.entity.MinestomEntityType; import com.dfsek.terra.minestom.item.MinestomItemHandle; - import com.dfsek.terra.minestom.world.MinestomChunkGeneratorWrapper; import com.dfsek.terra.minestom.world.MinestomWorldHandle; - import net.minestom.server.MinecraftServer; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.util.ArrayList; public final class MinestomPlatform extends AbstractPlatform { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java index f74ba415e..9cb3eb960 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/biome/MinestomBiomeLoader.java @@ -25,7 +25,7 @@ public class MinestomBiomeLoader implements TypeLoader { String id = (String) o; NamespaceID biomeID = NamespaceID.from(id); Biome biome = biomeRegistry.get(biomeID); - if (biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker); + if(biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker); return new MinestomBiome(biome); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java index cc455e133..01bad55fa 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockState.java @@ -15,26 +15,26 @@ public class MinestomBlockState implements BlockState { private final Block block; public MinestomBlockState(Block block) { - if (block == null) { + if(block == null) { this.block = Block.AIR; } else { this.block = block; } } - + public MinestomBlockState(String data) { - if (!data.contains("[")) { + if(!data.contains("[")) { block = Block.fromNamespaceId(data); return; } - + String[] split = data.split("\\["); String namespaceId = split[0]; String properties = split[1].substring(0, split[1].length() - 1); Block block = Block.fromNamespaceId(namespaceId); HashMap propertiesMap = new HashMap<>(); - for (String property : properties.split(",")) { + for(String property : properties.split(",")) { String[] kv = property.split("="); propertiesMap.put(kv[0].strip(), kv[1].strip()); } @@ -71,18 +71,12 @@ public class MinestomBlockState implements BlockState { @Override public String getAsString(boolean properties) { String name = block.namespace().asString(); - if (!properties || block.properties().isEmpty()) { + if(!properties || block.properties().isEmpty()) { return name; } - name += "[" + block - .properties() - .entrySet() - .stream() - .map(entry -> - entry.getKey() + "=" + entry.getValue() - ) - .collect(Collectors.joining(",")) + "]"; + name += "[" + block.properties().entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).collect( + Collectors.joining(",")) + "]"; return name; } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java index 36c5ce42d..8e4bd4360 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/block/MinestomBlockType.java @@ -40,7 +40,7 @@ public class MinestomBlockType implements BlockType { @Override public boolean equals(Object obj) { - if (obj instanceof MinestomBlockType other) { + if(obj instanceof MinestomBlockType other) { return block.id() == other.block.id(); } return false; diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java index c60feebcc..018c82c72 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/GeneratedChunkCache.java @@ -27,26 +27,20 @@ public class GeneratedChunkCache { this.generator = generator; this.world = world; this.biomeProvider = world.getBiomeProvider(); - this.cache = Caffeine.newBuilder() - .maximumSize(128) - .recordStats() - .build((Pair key) -> generateChunk(key.getLeft(), key.getRight())); + this.cache = Caffeine.newBuilder().maximumSize(128).recordStats().build( + (Pair 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 - ); + generator.generateChunkData(chunk, world, biomeProvider, x, z); 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()); + log.info("Avg load time: {}ms | Hit rate: {}% | Load Count: {}", stats.averageLoadPenalty(), stats.hitRate() * 100, + stats.loadCount()); } public CachedChunk at(int x, int z) { diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java index 12f38ced3..fdcf01aa7 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/chunk/TerraMinestomChunk.java @@ -5,6 +5,7 @@ import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.minestom.block.MinestomBlockState; + import net.minestom.server.instance.block.Block; import org.jetbrains.annotations.NotNull; diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java index e80404ab9..c31983ed3 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemHandle.java @@ -23,11 +23,6 @@ public class MinestomItemHandle implements ItemHandle { @Override public Set getEnchantments() { - return MinecraftServer - .getEnchantmentRegistry() - .values() - .stream() - .map(MinestomEnchantment::new) - .collect(Collectors.toSet()); + return MinecraftServer.getEnchantmentRegistry().values().stream().map(MinestomEnchantment::new).collect(Collectors.toSet()); } } diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java index 3ed760a57..2b488a8c8 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomItemStack.java @@ -50,10 +50,8 @@ public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStac EnchantmentList enchantmentList = base.get(ItemComponent.ENCHANTMENTS); if(enchantmentList != null) { enchantmentList.enchantments().forEach((enchantmentKey, integer) -> { - enchantments.put(new MinestomEnchantment( - Objects.requireNonNull(MinecraftServer.getEnchantmentRegistry().get(enchantmentKey))), - integer - ); + enchantments.put( + new MinestomEnchantment(Objects.requireNonNull(MinecraftServer.getEnchantmentRegistry().get(enchantmentKey))), integer); }); } return new MinestomItemMeta(enchantments); @@ -63,12 +61,10 @@ public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStac public void setItemMeta(ItemMeta meta) { HashMap, Integer> enchantments = new HashMap<>(); DynamicRegistry registry = MinecraftServer.getEnchantmentRegistry(); - meta - .getEnchantments() - .forEach((key, value) -> { - MinestomEnchantment enchantment = (MinestomEnchantment) key; - enchantments.put(registry.getKey(enchantment.getHandle()), value); - }); + meta.getEnchantments().forEach((key, value) -> { + MinestomEnchantment enchantment = (MinestomEnchantment) key; + enchantments.put(registry.getKey(enchantment.getHandle()), value); + }); EnchantmentList list = new EnchantmentList(enchantments); base = base.with(ItemComponent.ENCHANTMENTS, list); diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java index 2bd1e6a97..6bd0a1908 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/item/MinestomMaterial.java @@ -19,12 +19,7 @@ public class MinestomMaterial implements Item { @Override public ItemStack newItemStack(int amount) { - return new MinestomItemStack( - net.minestom.server.item.ItemStack - .builder(delegate) - .amount(amount) - .build() - ); + return new MinestomItemStack(net.minestom.server.item.ItemStack.builder(delegate).amount(amount).build()); } @Override diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java index e4cab993f..65ec22654 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/MinestomProtoWorld.java @@ -25,13 +25,7 @@ public class MinestomProtoWorld implements ProtoWorld { private final TerraMinestomWorld world; private final Setter modifier; - public MinestomProtoWorld( - GeneratedChunkCache cache, - int x, - int z, - TerraMinestomWorld world, - Setter modifier - ) { + public MinestomProtoWorld(GeneratedChunkCache cache, int x, int z, TerraMinestomWorld world, Setter modifier) { this.cache = cache; this.x = x; this.z = z; 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 0cce989cf..4f4aef091 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 @@ -37,13 +37,8 @@ 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(Instance instance, ConfigPack pack, long seed, EntityFactory entityFactory, + BlockEntityFactory blockEntityFactory) { this.instance = instance; this.pack = pack; this.seed = seed; @@ -51,11 +46,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(pack.getGeneratorProvider().newInstance(pack), this, pack); this.entityFactory = entityFactory; instance.setGenerator(this.wrapper); diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java index 7d04d6c9c..46ae1691c 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/world/TerraMinestomWorldBuilder.java @@ -9,6 +9,7 @@ import com.dfsek.terra.minestom.api.BlockEntityFactory; import com.dfsek.terra.minestom.api.EntityFactory; import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory; import com.dfsek.terra.minestom.entity.DefaultEntityFactory; + import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; @@ -39,11 +40,7 @@ public class TerraMinestomWorldBuilder { } public TerraMinestomWorldBuilder packById(String id) { - this.pack = MinestomPlatform - .getInstance() - .getConfigRegistry() - .getByID(id) - .orElseThrow(); + this.pack = MinestomPlatform.getInstance().getConfigRegistry().getByID(id).orElseThrow(); return this; } From aecc003f23a6c183277ea30523f576cce2dbeab1 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 5 Jan 2025 16:49:20 +0100 Subject: [PATCH 22/25] fix: minestom and slf4j as transitive dependencies --- platforms/minestom/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts index b0732811c..69245df99 100644 --- a/platforms/minestom/build.gradle.kts +++ b/platforms/minestom/build.gradle.kts @@ -9,8 +9,8 @@ dependencies { shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine) shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava) - implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) - implementation("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j) + compileOnly("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) + compileOnly("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j) } tasks.withType { From 810d10ac0ad25b19183e92820b39e50a4c9f9878 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 5 Jan 2025 16:58:28 +0100 Subject: [PATCH 23/25] fix: move minestom example to own module --- build.gradle.kts | 1 + platforms/minestom/build.gradle.kts | 20 ------------- platforms/minestom/example/build.gradle.kts | 28 +++++++++++++++++++ .../terra/minestom/TerraMinestomExample.java | 7 ++--- settings.gradle.kts | 1 + 5 files changed, 33 insertions(+), 24 deletions(-) create mode 100644 platforms/minestom/example/build.gradle.kts rename platforms/minestom/{ => example}/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java (98%) diff --git a/build.gradle.kts b/build.gradle.kts index 2d6105c73..44ca08e95 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,6 +44,7 @@ afterEvaluate { configureDistribution() } project(":platforms:bukkit:common").configureDistribution() + project(":platforms:minestom:example").configureDistribution() forSubProjects(":common:addons") { apply(plugin = "com.gradleup.shadow") diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts index 69245df99..a70848a32 100644 --- a/platforms/minestom/build.gradle.kts +++ b/platforms/minestom/build.gradle.kts @@ -2,34 +2,14 @@ plugins { application } -val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample" - dependencies { shadedApi(project(":common:implementation:base")) shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine) shadedImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava) compileOnly("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) - compileOnly("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j) -} - -tasks.withType { - entryCompression = ZipEntryCompression.STORED - manifest { - attributes( - "Main-Class" to javaMainClass, - ) - } -} - -application { - mainClass.set(javaMainClass) } tasks.named("jar") { finalizedBy("installAddonsIntoDefaultJar") } - -tasks.getByName("run").setProperty("workingDir", file("./run")) - -addonDir(project.file("./run/terra/addons"), tasks.named("run").get()) diff --git a/platforms/minestom/example/build.gradle.kts b/platforms/minestom/example/build.gradle.kts new file mode 100644 index 000000000..31d903136 --- /dev/null +++ b/platforms/minestom/example/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + application +} + +val javaMainClass = "com.dfsek.terra.minestom.TerraMinestomExample" + +dependencies { + shadedApi(project(":platforms:minestom")) + + implementation("net.minestom", "minestom-snapshots", Versions.Minestom.minestom) + implementation("org.slf4j", "slf4j-simple", Versions.Libraries.slf4j) +} + +tasks.withType { + entryCompression = ZipEntryCompression.STORED + manifest { + attributes( + "Main-Class" to javaMainClass, + ) + } +} + +application { + mainClass.set(javaMainClass) +} + +tasks.getByName("run").setProperty("workingDir", file("./run")) +addonDir(project.file("./run/terra/addons"), tasks.named("run").get()) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java b/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java similarity index 98% rename from platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java rename to platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java index 20dd10bbd..1cf95a226 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java +++ b/platforms/minestom/example/src/main/java/com/dfsek/terra/minestom/TerraMinestomExample.java @@ -1,12 +1,8 @@ package com.dfsek.terra.minestom; -import com.dfsek.terra.minestom.world.TerraMinestomWorld; -import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; - import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.command.builder.Command; -import net.minestom.server.command.builder.arguments.number.ArgumentInteger; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.GameMode; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; @@ -19,6 +15,9 @@ import org.slf4j.LoggerFactory; import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; +import com.dfsek.terra.minestom.world.TerraMinestomWorld; +import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder; + public class TerraMinestomExample { private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class); diff --git a/settings.gradle.kts b/settings.gradle.kts index c5bed6f73..86bb41bfb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,7 @@ includeImmediateChildren(file("platforms"), "platform") includeImmediateChildren(file("platforms/bukkit/nms"), "Bukkit NMS") include(":platforms:bukkit:common") +include(":platforms:minestom:example") pluginManagement { repositories { From 7b29d2584722e78070180e8b80b36a4668a6fa00 Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sun, 5 Jan 2025 17:04:27 +0100 Subject: [PATCH 24/25] fix: remove unused application plugin from Minestom platform build script --- platforms/minestom/build.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platforms/minestom/build.gradle.kts b/platforms/minestom/build.gradle.kts index a70848a32..59b775220 100644 --- a/platforms/minestom/build.gradle.kts +++ b/platforms/minestom/build.gradle.kts @@ -1,7 +1,3 @@ -plugins { - application -} - dependencies { shadedApi(project(":common:implementation:base")) shadedApi("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine) From 3a7d1a69d0902b6312c08c2ac8e1957d5340b74d Mon Sep 17 00:00:00 2001 From: Christian Bergschneider Date: Sat, 25 Jan 2025 04:42:52 +0100 Subject: [PATCH 25/25] feat: use system property for configurable data folder path Updated `getDataFolder` to allow customization via the `terra.datafolder` system property. This ensures greater flexibility for specifying the data folder location, while maintaining the default path if the property is not set. --- .../main/java/com/dfsek/terra/minestom/MinestomPlatform.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java index 5dd149133..7e6c6e0b5 100644 --- a/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java +++ b/platforms/minestom/src/main/java/com/dfsek/terra/minestom/MinestomPlatform.java @@ -77,7 +77,9 @@ public final class MinestomPlatform extends AbstractPlatform { @Override public @NotNull File getDataFolder() { - File file = new File("./terra/"); + String pathName = System.getProperty("terra.datafolder"); + if (pathName == null) pathName = "./terra/"; + File file = new File(pathName); if(!file.exists()) file.mkdirs(); return file; }