diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/BannerBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/BannerBlockHandler.java new file mode 100644 index 00000000..ae36216f --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/BannerBlockHandler.java @@ -0,0 +1,38 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; +import java.util.List; + +public class BannerBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "banner"); + + public static final Tag PATTERNS = Tag.NBT("patterns"); + public static final Tag CUSTOM_NAME = Tag.NBT("CustomName"); + + private static final List> TAGS = List.of( + PATTERNS, + CUSTOM_NAME + ); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/BlockHandlers.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/BlockHandlers.java new file mode 100644 index 00000000..212f9693 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/BlockHandlers.java @@ -0,0 +1,41 @@ +package net.onelitefeather.cygnus.common.block; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.instance.block.BlockManager; + +/** + * Utility class for registering standard {@link BlockHandler}s. + */ +public final class BlockHandlers { + + private BlockHandlers() { + } + + /** + * Registers default BlockHandlers on the global {@link BlockManager}. + */ + public static void registerAll() { + registerAll(MinecraftServer.getBlockManager()); + } + + /** + * Registers default BlockHandlers on the specified {@link BlockManager}. + * + * @param blockManager the block manager to register handlers on + */ + public static void registerAll(BlockManager blockManager) { + register(blockManager, new SignBlockHandler()); + register(blockManager, new HangingSignBlockHandler()); + register(blockManager, new ShelfBlockHandler()); + register(blockManager, new ChiseledBookshelfBlockHandler()); + register(blockManager, new BannerBlockHandler()); + register(blockManager, new LecternBlockHandler()); + register(blockManager, new CampfireBlockHandler()); + register(blockManager, new SoulCampfireBlockHandler()); + } + + private static void register(BlockManager blockManager, BlockHandler handler) { + blockManager.registerHandler(handler.getKey(), () -> handler); + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/CampfireBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/CampfireBlockHandler.java new file mode 100644 index 00000000..455c885b --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/CampfireBlockHandler.java @@ -0,0 +1,40 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; +import java.util.List; + +public class CampfireBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "campfire"); + + public static final Tag ITEMS = Tag.NBT("Items"); + public static final Tag COOKING_TIMES = Tag.NBT("CookingTimes"); + public static final Tag COOKING_TOTAL_TIMES = Tag.NBT("CookingTotalTimes"); + + static final List> TAGS = List.of( + ITEMS, + COOKING_TIMES, + COOKING_TOTAL_TIMES + ); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/ChiseledBookshelfBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/ChiseledBookshelfBlockHandler.java new file mode 100644 index 00000000..6f7deb6b --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/ChiseledBookshelfBlockHandler.java @@ -0,0 +1,28 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; + +public class ChiseledBookshelfBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "chiseled_bookshelf"); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return ShelfBlockHandler.TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/HangingSignBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/HangingSignBlockHandler.java new file mode 100644 index 00000000..6e8a3b0c --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/HangingSignBlockHandler.java @@ -0,0 +1,28 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; + +public class HangingSignBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "hanging_sign"); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return SignBlockHandler.TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/LecternBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/LecternBlockHandler.java new file mode 100644 index 00000000..5a2c0095 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/LecternBlockHandler.java @@ -0,0 +1,38 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; +import java.util.List; + +public class LecternBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "lectern"); + + public static final Tag BOOK = Tag.NBT("Book"); + public static final Tag PAGE = Tag.Integer("Page"); + + private static final List> TAGS = List.of( + BOOK, + PAGE + ); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandler.java new file mode 100644 index 00000000..a4f15577 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandler.java @@ -0,0 +1,38 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; +import java.util.List; + +public class ShelfBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "shelf"); + + public static final Tag ITEMS = Tag.NBT("Items"); + public static final Tag LAST_INTERACTED_SLOT = Tag.Integer("last_interacted_slot"); + + static final List> TAGS = List.of( + ITEMS, + LAST_INTERACTED_SLOT + ); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/SignBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/SignBlockHandler.java new file mode 100644 index 00000000..c517fad4 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/SignBlockHandler.java @@ -0,0 +1,40 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.BinaryTag; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; +import java.util.List; + +public class SignBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "sign"); + + public static final Tag IS_WAXED = Tag.Byte("is_waxed"); + public static final Tag FRONT_TEXT = Tag.NBT("front_text"); + public static final Tag BACK_TEXT = Tag.NBT("back_text"); + + static final List> TAGS = List.of( + IS_WAXED, + FRONT_TEXT, + BACK_TEXT + ); + + /** + * {@inheritDoc} + */ + @Override + public Key getKey() { + return KEY; + } + + /** + * {@inheritDoc} + */ + @Override + public Collection> getBlockEntityTags() { + return TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/SoulCampfireBlockHandler.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/SoulCampfireBlockHandler.java new file mode 100644 index 00000000..4b4a8e92 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/SoulCampfireBlockHandler.java @@ -0,0 +1,22 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.minestom.server.instance.block.BlockHandler; +import net.minestom.server.tag.Tag; + +import java.util.Collection; + +public class SoulCampfireBlockHandler implements BlockHandler { + + private static final Key KEY = Key.key("minecraft", "soul_campfire"); + + @Override + public Key getKey() { + return KEY; + } + + @Override + public Collection> getBlockEntityTags() { + return CampfireBlockHandler.TAGS; + } +} diff --git a/common/src/main/java/net/onelitefeather/cygnus/common/block/package-info.java b/common/src/main/java/net/onelitefeather/cygnus/common/block/package-info.java new file mode 100644 index 00000000..8fd1bc25 --- /dev/null +++ b/common/src/main/java/net/onelitefeather/cygnus/common/block/package-info.java @@ -0,0 +1,5 @@ + +@NotNullByDefault +package net.onelitefeather.cygnus.common.block; + +import org.jetbrains.annotations.NotNullByDefault; \ No newline at end of file diff --git a/common/src/test/java/net/onelitefeather/cygnus/common/block/BlockHandlersTest.java b/common/src/test/java/net/onelitefeather/cygnus/common/block/BlockHandlersTest.java new file mode 100644 index 00000000..934c257c --- /dev/null +++ b/common/src/test/java/net/onelitefeather/cygnus/common/block/BlockHandlersTest.java @@ -0,0 +1,29 @@ +package net.onelitefeather.cygnus.common.block; + +import net.minestom.server.instance.block.BlockManager; +import net.minestom.testing.Env; +import net.minestom.testing.extension.MicrotusExtension; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@ExtendWith(MicrotusExtension.class) +class BlockHandlersTest { + + @Test + void testRegisterAll(@NotNull Env env) { + BlockManager blockManager = env.process().block(); + BlockHandlers.registerAll(blockManager); + + assertNotNull(blockManager.getHandler("minecraft:sign")); + assertNotNull(blockManager.getHandler("minecraft:hanging_sign")); + assertNotNull(blockManager.getHandler("minecraft:shelf")); + assertNotNull(blockManager.getHandler("minecraft:chiseled_bookshelf")); + assertNotNull(blockManager.getHandler("minecraft:banner")); + assertNotNull(blockManager.getHandler("minecraft:lectern")); + assertNotNull(blockManager.getHandler("minecraft:campfire")); + assertNotNull(blockManager.getHandler("minecraft:soul_campfire")); + } +} diff --git a/common/src/test/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandlerTest.java b/common/src/test/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandlerTest.java new file mode 100644 index 00000000..0e11ccf8 --- /dev/null +++ b/common/src/test/java/net/onelitefeather/cygnus/common/block/ShelfBlockHandlerTest.java @@ -0,0 +1,60 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.nbt.ListBinaryTag; +import net.minestom.server.instance.block.Block; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ShelfBlockHandlerTest { + + @Test + void testShelfKey() { + ShelfBlockHandler handler = new ShelfBlockHandler(); + assertEquals(Key.key("minecraft:shelf"), handler.getKey()); + } + + @Test + void testChiseledBookshelfKey() { + ChiseledBookshelfBlockHandler handler = new ChiseledBookshelfBlockHandler(); + assertEquals(Key.key("minecraft:chiseled_bookshelf"), handler.getKey()); + } + + @Test + void testBlockEntityTags() { + ShelfBlockHandler handler = new ShelfBlockHandler(); + var tags = handler.getBlockEntityTags(); + + assertEquals(2, tags.size()); + assertTrue(tags.contains(ShelfBlockHandler.ITEMS)); + assertTrue(tags.contains(ShelfBlockHandler.LAST_INTERACTED_SLOT)); + + ChiseledBookshelfBlockHandler chiseledHandler = new ChiseledBookshelfBlockHandler(); + assertEquals(tags, chiseledHandler.getBlockEntityTags()); + } + + @Test + void testBlockWithHandlerPreservesTags() { + ShelfBlockHandler handler = new ShelfBlockHandler(); + CompoundBinaryTag item = CompoundBinaryTag.builder() + .putByte("Slot", (byte) 0) + .putString("id", "minecraft:written_book") + .putByte("Count", (byte) 1) + .build(); + ListBinaryTag itemsList = ListBinaryTag.builder().add(item).build(); + + Block block = Block.CHISELED_BOOKSHELF + .withHandler(handler) + .withTag(ShelfBlockHandler.ITEMS, itemsList) + .withTag(ShelfBlockHandler.LAST_INTERACTED_SLOT, 0); + + assertNotNull(block.handler()); + assertEquals(handler, block.handler()); + assertEquals(itemsList, block.getTag(ShelfBlockHandler.ITEMS)); + assertEquals(0, block.getTag(ShelfBlockHandler.LAST_INTERACTED_SLOT)); + } +} diff --git a/common/src/test/java/net/onelitefeather/cygnus/common/block/SignBlockHandlerTest.java b/common/src/test/java/net/onelitefeather/cygnus/common/block/SignBlockHandlerTest.java new file mode 100644 index 00000000..9231dd6c --- /dev/null +++ b/common/src/test/java/net/onelitefeather/cygnus/common/block/SignBlockHandlerTest.java @@ -0,0 +1,58 @@ +package net.onelitefeather.cygnus.common.block; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.minestom.server.instance.block.Block; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class SignBlockHandlerTest { + + @Test + void testSignKey() { + SignBlockHandler handler = new SignBlockHandler(); + assertEquals(Key.key("minecraft:sign"), handler.getKey()); + } + + @Test + void testHangingSignKey() { + HangingSignBlockHandler handler = new HangingSignBlockHandler(); + assertEquals(Key.key("minecraft:hanging_sign"), handler.getKey()); + } + + @Test + void testBlockEntityTags() { + SignBlockHandler handler = new SignBlockHandler(); + var tags = handler.getBlockEntityTags(); + + assertEquals(3, tags.size()); + assertTrue(tags.contains(SignBlockHandler.IS_WAXED)); + assertTrue(tags.contains(SignBlockHandler.FRONT_TEXT)); + assertTrue(tags.contains(SignBlockHandler.BACK_TEXT)); + + HangingSignBlockHandler hangingHandler = new HangingSignBlockHandler(); + assertEquals(tags, hangingHandler.getBlockEntityTags()); + } + + @Test + void testBlockWithHandlerPreservesTags() { + SignBlockHandler handler = new SignBlockHandler(); + CompoundBinaryTag frontText = CompoundBinaryTag.builder() + .putString("color", "black") + .putByte("has_glowing_text", (byte) 0) + .build(); + + Block block = Block.OAK_SIGN + .withHandler(handler) + .withTag(SignBlockHandler.FRONT_TEXT, frontText) + .withTag(SignBlockHandler.IS_WAXED, (byte) 1); + + assertNotNull(block.handler()); + assertEquals(handler, block.handler()); + assertEquals(frontText, block.getTag(SignBlockHandler.FRONT_TEXT)); + assertEquals((byte) 1, block.getTag(SignBlockHandler.IS_WAXED)); + } +} diff --git a/game/src/main/java/net/onelitefeather/cygnus/CygnusLoader.java b/game/src/main/java/net/onelitefeather/cygnus/CygnusLoader.java index e8bb1ab6..a3956a1d 100644 --- a/game/src/main/java/net/onelitefeather/cygnus/CygnusLoader.java +++ b/game/src/main/java/net/onelitefeather/cygnus/CygnusLoader.java @@ -1,6 +1,7 @@ package net.onelitefeather.cygnus; import net.hollowcube.minestom.extensions.ExtensionBootstrap; +import net.onelitefeather.cygnus.common.block.BlockHandlers; import net.onelitefeather.cygnus.common.bootstrap.ServiceBootstrap; import net.onelitefeather.cygnus.common.dimension.DimensionFactory; import net.onelitefeather.cygnus.common.permission.LuckPermsSupport; @@ -13,6 +14,7 @@ static void main() { // standalone simply loads none. This also performs MinecraftServer.init(). ExtensionBootstrap bootstrap = ExtensionBootstrap.init(); LuckPermsSupport.bootstrap(); + BlockHandlers.registerAll(); String customDimensions = System.getProperty("cygnus.customDimension", "false"); if (Boolean.parseBoolean(customDimensions)) { DimensionFactory.registerAll();