From 25b39a573af2c1ea3f730f63e1740f9ee7ba7e51 Mon Sep 17 00:00:00 2001 From: Aaron Date: Sun, 14 Jan 2024 22:50:36 +0100 Subject: [PATCH] feat: added world extra data --- .../sculkpowered/server/world/World.java | 17 +++++++++++ .../server/world/WorldLoader.java | 27 ++++++++++++----- .../sculkpowered/server/world/WorldSaver.java | 11 +++++-- .../sculkpowered/server/SculkServer.java | 11 +++++++ .../sculkpowered/server/world/SculkWorld.java | 12 ++++++++ .../server/world/SlimeFormat.java | 29 +++++++++---------- .../world/chunk/loader/AnvilLoader.java | 2 +- 7 files changed, 81 insertions(+), 28 deletions(-) diff --git a/api/src/main/java/io/github/sculkpowered/server/world/World.java b/api/src/main/java/io/github/sculkpowered/server/world/World.java index eca0fe8e..449b3a94 100644 --- a/api/src/main/java/io/github/sculkpowered/server/world/World.java +++ b/api/src/main/java/io/github/sculkpowered/server/world/World.java @@ -7,6 +7,7 @@ import io.github.sculkpowered.server.world.chunk.ChunkGenerator; import io.github.sculkpowered.server.world.chunk.VoidGenerator; import io.github.sculkpowered.server.world.dimension.Dimension; +import net.kyori.adventure.nbt.CompoundBinaryTag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -137,6 +138,22 @@ default void block(@NotNull Position position, @NotNull BlockState block) { */ void spawnEntity(@NotNull Entity entity, @NotNull Position position); + /** + * Gets the extra world data. + * In the anvil folder it is the level dat file. + * + * @since 1.0.0 + */ + @NotNull CompoundBinaryTag extraData(); + + /** + * Sets the extra data. + * + * @param data the data in a compound binary tag + * @since 1.0.0 + */ + void extraData(@NotNull CompoundBinaryTag data); + /** * Checks if the world is alive. * diff --git a/api/src/main/java/io/github/sculkpowered/server/world/WorldLoader.java b/api/src/main/java/io/github/sculkpowered/server/world/WorldLoader.java index 5ba7a4ec..0f6507ef 100644 --- a/api/src/main/java/io/github/sculkpowered/server/world/WorldLoader.java +++ b/api/src/main/java/io/github/sculkpowered/server/world/WorldLoader.java @@ -1,6 +1,9 @@ package io.github.sculkpowered.server.world; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import org.jetbrains.annotations.NotNull; @@ -38,11 +41,19 @@ public boolean entities() { } public static @NotNull Slime slime(byte @NotNull [] bytes) { - return new Slime(bytes); + return slime(new ByteArrayInputStream(bytes)); } - public static @NotNull WorldLoader slime(@NotNull Path path) throws IOException { - return slime(Files.readAllBytes(path)); + public static @NotNull Slime slime(@NotNull Path path) throws IOException { + return slime(Files.newInputStream(path)); + } + + public static @NotNull Slime slime(@NotNull InputStream inputStream) { + return slime(new DataInputStream(inputStream)); + } + + public static @NotNull Slime slime(@NotNull DataInputStream inputStream) { + return new Slime(inputStream); } public static final class Anvil extends WorldLoader { @@ -60,14 +71,14 @@ public Path path() { public static final class Slime extends WorldLoader { - private final byte[] bytes; + private final DataInputStream inputStream; - public Slime(byte[] bytes) { - this.bytes = bytes; + public Slime(DataInputStream inputStream) { + this.inputStream = inputStream; } - public byte[] bytes() { - return this.bytes; + public DataInputStream inputStream() { + return this.inputStream; } } } diff --git a/api/src/main/java/io/github/sculkpowered/server/world/WorldSaver.java b/api/src/main/java/io/github/sculkpowered/server/world/WorldSaver.java index 7560204e..db773809 100644 --- a/api/src/main/java/io/github/sculkpowered/server/world/WorldSaver.java +++ b/api/src/main/java/io/github/sculkpowered/server/world/WorldSaver.java @@ -1,5 +1,6 @@ package io.github.sculkpowered.server.world; +import java.io.DataOutputStream; import java.io.OutputStream; import java.nio.file.Path; import org.jetbrains.annotations.NotNull; @@ -14,6 +15,10 @@ private WorldSaver() { } public static @NotNull Slime slime(@NotNull OutputStream outputStream) { + return slime(new DataOutputStream(outputStream)); + } + + public static @NotNull Slime slime(@NotNull DataOutputStream outputStream) { return new Slime(outputStream); } @@ -32,13 +37,13 @@ public Path path() { public static final class Slime extends WorldSaver { - private final OutputStream outputStream; + private final DataOutputStream outputStream; - public Slime(OutputStream outputStream) { + public Slime(DataOutputStream outputStream) { this.outputStream = outputStream; } - public OutputStream outputStream() { + public DataOutputStream outputStream() { return this.outputStream; } } diff --git a/server/src/main/java/io/github/sculkpowered/server/SculkServer.java b/server/src/main/java/io/github/sculkpowered/server/SculkServer.java index d2c13701..a0cafbfb 100644 --- a/server/src/main/java/io/github/sculkpowered/server/SculkServer.java +++ b/server/src/main/java/io/github/sculkpowered/server/SculkServer.java @@ -69,6 +69,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import net.kyori.adventure.nbt.BinaryTagIO; +import net.kyori.adventure.nbt.BinaryTagIO.Compression; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.apache.logging.log4j.LogManager; @@ -304,6 +306,15 @@ public int playerCount() { final var world = this.createWorld(builder, chunkLoader); if (loader instanceof WorldLoader.Slime slime) { SlimeFormat.load(this, (SculkWorld) world, slime); + } else if (loader instanceof WorldLoader.Anvil anvil) { + final var levelData = anvil.path().resolve("level.dat"); + if (Files.exists(levelData)) { + try { + world.extraData(BinaryTagIO.reader().read(levelData, Compression.GZIP)); + } catch (IOException e) { + LOGGER.warn("Error during level data loading: ", e); + } + } } return world; } diff --git a/server/src/main/java/io/github/sculkpowered/server/world/SculkWorld.java b/server/src/main/java/io/github/sculkpowered/server/world/SculkWorld.java index c1210685..4c5d0c7b 100644 --- a/server/src/main/java/io/github/sculkpowered/server/world/SculkWorld.java +++ b/server/src/main/java/io/github/sculkpowered/server/world/SculkWorld.java @@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import java.util.function.Consumer; +import net.kyori.adventure.nbt.CompoundBinaryTag; import org.jetbrains.annotations.NotNull; public final class SculkWorld implements World { @@ -25,6 +26,7 @@ public final class SculkWorld implements World { private final Position spawnPosition; private final GameMode defaultGameMode; private final Long2ObjectMap chunks; + private CompoundBinaryTag extraData = CompoundBinaryTag.empty(); private boolean alive; public SculkWorld( @@ -109,6 +111,16 @@ public void spawnEntity(@NotNull Entity entity, @NotNull Position position) { } } + @Override + public @NotNull CompoundBinaryTag extraData() { + return this.extraData; + } + + @Override + public void extraData(@NotNull CompoundBinaryTag data) { + this.extraData = data; + } + @Override public boolean isAlive() { return this.alive; diff --git a/server/src/main/java/io/github/sculkpowered/server/world/SlimeFormat.java b/server/src/main/java/io/github/sculkpowered/server/world/SlimeFormat.java index 6a948407..9f985554 100644 --- a/server/src/main/java/io/github/sculkpowered/server/world/SlimeFormat.java +++ b/server/src/main/java/io/github/sculkpowered/server/world/SlimeFormat.java @@ -17,7 +17,6 @@ import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.util.Collection; import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.CompoundBinaryTag; @@ -42,24 +41,22 @@ public static void load( final SculkWorld world, final WorldLoader.Slime loader ) { - try (final var inputStream = new DataInputStream(new ByteArrayInputStream(loader.bytes()))) { + try (final var inputStream = loader.inputStream()) { if (inputStream.readShort() != HEADER) { throw new AssertionError(); } final var version = inputStream.readUnsignedByte(); - if (version != VERSION_10 && version != VERSION_11) { - throw new UnsupportedOperationException( - "Currently only slime version 10 and 11 are supported!"); - } inputStream.readInt(); // world version - - if (version == VERSION_10) { - readChunks10(server, world, readCompressed(inputStream)); - readEntities(server, world, loader, inputStream); - } else { - readChunks11(server, world, loader, readCompressed(inputStream)); + switch (version) { + case VERSION_10 -> { + readChunks10(server, world, readCompressed(inputStream)); + readEntities(server, world, loader, inputStream); + } + case VERSION_11 -> readChunks11(server, world, loader, readCompressed(inputStream)); + default -> throw new UnsupportedOperationException("Slime version " + version + " not supported!"); } - readCompressed(inputStream); + + world.extraData(readCompound(readCompressed(inputStream))); } catch (IOException e) { LOGGER.error("Couldn't load slime world", e); } @@ -196,8 +193,8 @@ private static CompoundBinaryTag readCompound(final byte[] data) throws IOExcept // SAVING public static void save(final SculkServer server, final SculkWorld world, - final OutputStream outputStream) { - try (final var dataOutput = new DataOutputStream(outputStream)) { + final DataOutputStream outputStream) { + try (final var dataOutput = outputStream) { dataOutput.writeShort(HEADER); dataOutput.writeByte(VERSION_10); dataOutput.writeInt(3465); @@ -240,7 +237,7 @@ public static void save(final SculkServer server, final SculkWorld world, CompoundBinaryTag.builder().put("tiles", tiles.build()).build()); writeCompoundCompressed(dataOutput, CompoundBinaryTag.builder().put("entities", entities.build()).build()); - writeCompoundCompressed(dataOutput, CompoundBinaryTag.empty()); + writeCompoundCompressed(dataOutput, world.extraData()); } catch (IOException e) { LOGGER.error("Error while saving world", e); } diff --git a/server/src/main/java/io/github/sculkpowered/server/world/chunk/loader/AnvilLoader.java b/server/src/main/java/io/github/sculkpowered/server/world/chunk/loader/AnvilLoader.java index b74f25ef..a46b3973 100644 --- a/server/src/main/java/io/github/sculkpowered/server/world/chunk/loader/AnvilLoader.java +++ b/server/src/main/java/io/github/sculkpowered/server/world/chunk/loader/AnvilLoader.java @@ -45,7 +45,7 @@ public AnvilLoader(final SculkServer server, final ChunkGenerator generator, @Override public @NotNull SculkChunk loadChunk(final SculkWorld world, final int x, final int z) { final var fileName = - "r." + CoordinateUtil.regionCoordinate(x) + "." + CoordinateUtil.regionCoordinate(z) + "r." + CoordinateUtil.regionCoordinate(x) + '.' + CoordinateUtil.regionCoordinate(z) + ".mca"; try { SculkChunk chunk;