From 38aa191ba27fad130dc36e05de87385fe9c41416 Mon Sep 17 00:00:00 2001 From: glisco Date: Sun, 18 Aug 2024 23:33:26 +0200 Subject: [PATCH] make 'get-lavender-book' command client-side and expand to appropriate /give invocation when executed --- .../java/io/wispforest/lavender/Lavender.java | 5 - .../wispforest/lavender/LavenderCommands.java | 99 ++++++++++++------- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/src/main/java/io/wispforest/lavender/Lavender.java b/src/main/java/io/wispforest/lavender/Lavender.java index 894c06d..202d687 100644 --- a/src/main/java/io/wispforest/lavender/Lavender.java +++ b/src/main/java/io/wispforest/lavender/Lavender.java @@ -7,7 +7,6 @@ import io.wispforest.lavender.book.LavenderBookItem; import io.wispforest.owo.serialization.CodecUtils; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.minecraft.datafixer.DataFixTypes; @@ -30,15 +29,11 @@ public class Lavender implements ModInitializer { public static final String MOD_ID = "lavender"; public static final SoundEvent ITEM_BOOK_OPEN = SoundEvent.of(id("item.book.open")); - public static final Identifier WORLD_ID_CHANNEL = Lavender.id("world_id_channel"); - @Override public void onInitialize() { Registry.register(Registries.ITEM, id("dynamic_book"), LavenderBookItem.DYNAMIC_BOOK); Registry.register(Registries.SOUND_EVENT, ITEM_BOOK_OPEN.getId(), ITEM_BOOK_OPEN); - CommandRegistrationCallback.EVENT.register(LavenderCommands::register); - PayloadTypeRegistry.playS2C().register(WorldUUIDPayload.ID, CodecUtils.toPacketCodec(WorldUUIDPayload.ENDEC)); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { diff --git a/src/main/java/io/wispforest/lavender/LavenderCommands.java b/src/main/java/io/wispforest/lavender/LavenderCommands.java index 6ca95e8..d7093e1 100644 --- a/src/main/java/io/wispforest/lavender/LavenderCommands.java +++ b/src/main/java/io/wispforest/lavender/LavenderCommands.java @@ -7,56 +7,37 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.SuggestionProvider; import io.wispforest.lavender.book.Book; -import io.wispforest.lavender.book.LavenderBookItem; import io.wispforest.lavender.book.BookLoader; +import io.wispforest.lavender.book.LavenderBookItem; import io.wispforest.lavender.client.StructureOverlayRenderer; import io.wispforest.lavender.structure.LavenderStructures; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandSource; import net.minecraft.command.argument.IdentifierArgumentType; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.component.Component; +import net.minecraft.nbt.NbtOps; +import net.minecraft.registry.Registries; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; public class LavenderCommands { private static final SimpleCommandExceptionType NO_SUCH_BOOK = new SimpleCommandExceptionType(Text.literal("No such book is loaded")); - private static final SuggestionProvider LOADED_BOOKS = (context, builder) -> { + private static final SuggestionProvider LOADED_BOOKS = (context, builder) -> { return CommandSource.suggestIdentifiers(BookLoader.loadedBooks().stream().map(Book::id), builder); }; - public static void register(CommandDispatcher dispatcher, CommandRegistryAccess access, CommandManager.RegistrationEnvironment environment) { - dispatcher.register(literal("get-lavender-book") - .then(argument("book_id", IdentifierArgumentType.identifier()).suggests(LOADED_BOOKS) - .executes(context -> executeGetLavenderBook(context, false)) - .then(argument("force_dynamic_book", BoolArgumentType.bool()) - .executes(context -> executeGetLavenderBook(context, BoolArgumentType.getBool(context, "force_dynamic_book")))))); - - } - - private static int executeGetLavenderBook(CommandContext context, boolean forceDynamicBook) throws CommandSyntaxException { - var book = BookLoader.get(IdentifierArgumentType.getIdentifier(context, "book_id")); - if (book == null) { - throw NO_SUCH_BOOK.create(); - } - - context.getSource().getPlayer().getInventory().offerOrDrop(forceDynamicBook - ? LavenderBookItem.createDynamic(book) - : LavenderBookItem.itemOf(book) - ); - - return 0; - } - @Environment(EnvType.CLIENT) public static class Client { @@ -64,15 +45,65 @@ public static class Client { private static final SuggestionProvider STRUCTURE_INFO = (context, builder) -> CommandSource.suggestMatching(LavenderStructures.loadedStructures().stream().map(Identifier::toString), builder); + private static int executeGetLavenderBook(CommandContext context, boolean forceDynamicBook) throws CommandSyntaxException { + var book = BookLoader.get(context.getArgument("book_id", Identifier.class)); + if (book == null) { + throw NO_SUCH_BOOK.create(); + } + + var stack = forceDynamicBook + ? LavenderBookItem.createDynamic(book) + : LavenderBookItem.itemOf(book); + + var command = "/give @s " + Registries.ITEM.getId(stack.getItem()); + + var ops = context.getSource().getWorld().getRegistryManager().getOps(NbtOps.INSTANCE); + var components = stack.getComponentChanges().entrySet().stream().flatMap(entry -> { + var componentType = entry.getKey(); + var typeId = Registries.DATA_COMPONENT_TYPE.getId(componentType); + if (typeId == null) return Stream.empty(); + + var componentOptional = entry.getValue(); + if (componentOptional.isPresent()) { + Component component = Component.of(componentType, componentOptional.get()); + return component.encode(ops).result().stream().map(value -> typeId + "=" + value); + } else { + return Stream.of("!" + typeId); + } + }).collect(Collectors.joining(String.valueOf(','))); + + if (!components.isEmpty()) { + command += "[" + components + "]"; + } + + if (stack.getCount() > 1) { + command += " " + stack.getCount(); + } + + var jAvAsE = command; + context.getSource().getClient().send(() -> { + context.getSource().getClient().setScreen(new ChatScreen(jAvAsE)); + }); + + return 0; + } + public static void register(CommandDispatcher dispatcher, CommandRegistryAccess access) { - dispatcher.register(ClientCommandManager.literal("structure-overlay") - .then(ClientCommandManager.literal("clear-all").executes(context -> { + dispatcher.register(literal("get-lavender-book").requires(source -> source.hasPermissionLevel(2)) + .then(argument("book_id", IdentifierArgumentType.identifier()).suggests(LOADED_BOOKS) + .executes(context -> executeGetLavenderBook(context, false)) + .then(argument("force_dynamic_book", BoolArgumentType.bool()) + .executes(context -> executeGetLavenderBook(context, BoolArgumentType.getBool(context, "force_dynamic_book")))))); + + + dispatcher.register(literal("structure-overlay") + .then(literal("clear-all").executes(context -> { StructureOverlayRenderer.clearOverlays(); return 0; })) - .then(ClientCommandManager.literal("add") - .then(ClientCommandManager.argument("structure", IdentifierArgumentType.identifier()).suggests(STRUCTURE_INFO).executes(context -> { + .then(literal("add") + .then(argument("structure", IdentifierArgumentType.identifier()).suggests(STRUCTURE_INFO).executes(context -> { var structureId = context.getArgument("structure", Identifier.class); if (LavenderStructures.get(structureId) == null) throw NO_SUCH_STRUCTURE.create();