From a2e53592258f13947594e227f78a91053e63c030 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 12 Aug 2022 22:04:30 +0900 Subject: [PATCH 1/2] Add client commands Signed-off-by: shedaniel --- .../ClientCommandRegistrationEvent.java | 72 +++++++++++++++++++ .../event/fabric/EventHandlerImpl.java | 13 ++-- .../MixinFabricClientCommandSource.java | 62 ++++++++++++++++ .../main/resources/architectury.mixins.json | 1 + .../event/forge/EventHandlerImplClient.java | 7 ++ .../forge/client/MixinCommandSourceStack.java | 67 +++++++++++++++++ .../main/resources/architectury.mixins.json | 1 + .../java/dev/architectury/test/TestMod.java | 14 +++- 8 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 common/src/main/java/dev/architectury/event/events/client/ClientCommandRegistrationEvent.java create mode 100644 fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinFabricClientCommandSource.java create mode 100644 forge/src/main/java/dev/architectury/mixin/forge/client/MixinCommandSourceStack.java diff --git a/common/src/main/java/dev/architectury/event/events/client/ClientCommandRegistrationEvent.java b/common/src/main/java/dev/architectury/event/events/client/ClientCommandRegistrationEvent.java new file mode 100644 index 000000000..0298e4f72 --- /dev/null +++ b/common/src/main/java/dev/architectury/event/events/client/ClientCommandRegistrationEvent.java @@ -0,0 +1,72 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.event.events.client; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import dev.architectury.event.Event; +import dev.architectury.event.EventFactory; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; + +public interface ClientCommandRegistrationEvent { + /** + * @see ClientCommandRegistrationEvent#register(CommandDispatcher, CommandBuildContext) + */ + Event EVENT = EventFactory.createLoop(); + + /** + * This event is invoked after the client initializes. + * Equivalent to Forge's {@code RegisterClientCommandsEvent} and Fabric's {@code ClientCommandManager}. + * + * @param dispatcher The command dispatcher to register commands to. + * @param context The command build context. + */ + void register(CommandDispatcher dispatcher, CommandBuildContext context); + + static LiteralArgumentBuilder literal(String name) { + return LiteralArgumentBuilder.literal(name); + } + + static RequiredArgumentBuilder argument(String name, ArgumentType type) { + return RequiredArgumentBuilder.argument(name, type); + } + + interface ClientCommandSourceStack extends SharedSuggestionProvider { + void arch$sendSuccess(Component message, boolean broadcastToAdmins); + + void arch$sendFailure(Component message); + + LocalPlayer arch$getPlayer(); + + Vec3 arch$getPosition(); + + Vec2 arch$getRotation(); + + ClientLevel arch$getLevel(); + } +} diff --git a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java index 33a3a9428..1db8bfbb9 100644 --- a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java +++ b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java @@ -19,14 +19,13 @@ package dev.architectury.event.fabric; -import dev.architectury.event.events.client.ClientGuiEvent; -import dev.architectury.event.events.client.ClientLifecycleEvent; -import dev.architectury.event.events.client.ClientTickEvent; -import dev.architectury.event.events.client.ClientTooltipEvent; +import com.mojang.brigadier.CommandDispatcher; +import dev.architectury.event.events.client.*; import dev.architectury.event.events.common.*; import dev.architectury.impl.fabric.ChatComponentImpl; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; @@ -42,7 +41,6 @@ import net.fabricmc.fabric.api.loot.v2.LootTableEvents; import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent; import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; -import net.minecraft.network.chat.PlayerChatMessage; import java.util.concurrent.CompletableFuture; @@ -59,6 +57,11 @@ public static void registerClient() { ItemTooltipCallback.EVENT.register((itemStack, tooltipFlag, list) -> ClientTooltipEvent.ITEM.invoker().append(itemStack, list, tooltipFlag)); HudRenderCallback.EVENT.register((matrices, tickDelta) -> ClientGuiEvent.RENDER_HUD.invoker().renderHud(matrices, tickDelta)); + + ClientCommandRegistrationCallback.EVENT.register((dispatcher, access) -> { + ClientCommandRegistrationEvent.EVENT.invoker().register((CommandDispatcher) + (CommandDispatcher) dispatcher, access); + }); } public static void registerCommon() { diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinFabricClientCommandSource.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinFabricClientCommandSource.java new file mode 100644 index 000000000..2aa8544f9 --- /dev/null +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinFabricClientCommandSource.java @@ -0,0 +1,62 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.mixin.fabric.client; + +import dev.architectury.event.events.client.ClientCommandRegistrationEvent; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(FabricClientCommandSource.class) +public interface MixinFabricClientCommandSource extends ClientCommandRegistrationEvent.ClientCommandSourceStack { + @Override + default void arch$sendSuccess(Component message, boolean broadcastToAdmins) { + ((FabricClientCommandSource) this).sendFeedback(message); + } + + @Override + default void arch$sendFailure(Component message) { + ((FabricClientCommandSource) this).sendError(message); + } + + @Override + default LocalPlayer arch$getPlayer() { + return ((FabricClientCommandSource) this).getPlayer(); + } + + @Override + default Vec3 arch$getPosition() { + return ((FabricClientCommandSource) this).getPosition(); + } + + @Override + default Vec2 arch$getRotation() { + return ((FabricClientCommandSource) this).getRotation(); + } + + @Override + default ClientLevel arch$getLevel() { + return ((FabricClientCommandSource) this).getWorld(); + } +} diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index 363897b16..1e6354900 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -13,6 +13,7 @@ "client.MixinClientPacketListener", "client.MixinDebugScreenOverlay", "client.MixinEffectInstance", + "client.MixinFabricClientCommandSource", "client.MixinGameRenderer", "client.MixinIntegratedServer", "client.MixinKeyboardHandler", diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java index bbad9f991..403cd9f04 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java @@ -20,6 +20,7 @@ package dev.architectury.event.forge; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.brigadier.CommandDispatcher; import dev.architectury.event.CompoundEventResult; import dev.architectury.event.EventResult; import dev.architectury.event.events.client.ClientChatEvent; @@ -324,6 +325,12 @@ public static void eventInputEvent(InputEvent.Key event) { ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers()); } + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(RegisterClientCommandsEvent event) { + ClientCommandRegistrationEvent.EVENT.invoker().register((CommandDispatcher) + (CommandDispatcher) event.getDispatcher(), event.getBuildContext()); + } + @OnlyIn(Dist.CLIENT) public static class ModBasedEventHandler { @SubscribeEvent(priority = EventPriority.HIGH) diff --git a/forge/src/main/java/dev/architectury/mixin/forge/client/MixinCommandSourceStack.java b/forge/src/main/java/dev/architectury/mixin/forge/client/MixinCommandSourceStack.java new file mode 100644 index 000000000..65e6cc007 --- /dev/null +++ b/forge/src/main/java/dev/architectury/mixin/forge/client/MixinCommandSourceStack.java @@ -0,0 +1,67 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.mixin.forge.client; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import dev.architectury.event.events.client.ClientCommandRegistrationEvent; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.Component; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CommandSourceStack.class) +public abstract class MixinCommandSourceStack implements ClientCommandRegistrationEvent.ClientCommandSourceStack { + @Override + public void arch$sendSuccess(Component message, boolean broadcastToAdmins) { + ((CommandSourceStack) (Object) this).sendSuccess(message, broadcastToAdmins); + } + + @Override + public void arch$sendFailure(Component message) { + ((CommandSourceStack) (Object) this).sendFailure(message); + } + + @Override + public LocalPlayer arch$getPlayer() { + try { + return (LocalPlayer) ((CommandSourceStack) (Object) this).getEntityOrException(); + } catch (CommandSyntaxException e) { + throw new RuntimeException(e); + } + } + + @Override + public Vec3 arch$getPosition() { + return ((CommandSourceStack) (Object) this).getPosition(); + } + + @Override + public Vec2 arch$getRotation() { + return ((CommandSourceStack) (Object) this).getRotation(); + } + + @Override + public ClientLevel arch$getLevel() { + return (ClientLevel) ((CommandSourceStack) (Object) this).getUnsidedLevel(); + } +} diff --git a/forge/src/main/resources/architectury.mixins.json b/forge/src/main/resources/architectury.mixins.json index f2ee348f8..bc327cb60 100644 --- a/forge/src/main/resources/architectury.mixins.json +++ b/forge/src/main/resources/architectury.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_16", "minVersion": "0.8", "client": [ + "client.MixinCommandSourceStack", "MixinClientLevel", "MixinMinecraft" ], diff --git a/testmod-common/src/main/java/dev/architectury/test/TestMod.java b/testmod-common/src/main/java/dev/architectury/test/TestMod.java index 5829979b1..9fac583c7 100644 --- a/testmod-common/src/main/java/dev/architectury/test/TestMod.java +++ b/testmod-common/src/main/java/dev/architectury/test/TestMod.java @@ -19,13 +19,14 @@ package dev.architectury.test; +import com.mojang.brigadier.arguments.StringArgumentType; +import dev.architectury.event.events.client.ClientCommandRegistrationEvent; import dev.architectury.event.events.client.ClientLifecycleEvent; import dev.architectury.registry.client.gui.ClientTooltipComponentRegistry; import dev.architectury.registry.client.level.entity.EntityRendererRegistry; import dev.architectury.test.debug.ConsoleMessageSink; import dev.architectury.test.debug.MessageSink; import dev.architectury.test.debug.client.ClientOverlayMessageSink; -import dev.architectury.test.entity.TestEntity; import dev.architectury.test.events.DebugEvents; import dev.architectury.test.gamerule.TestGameRules; import dev.architectury.test.item.TestBlockInteractions; @@ -43,8 +44,6 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.renderer.entity.CowRenderer; -import net.minecraft.client.renderer.entity.PigRenderer; -import net.minecraft.world.entity.animal.Cow; public class TestMod { public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new); @@ -75,6 +74,15 @@ public static void initializeClient() { EntityRendererRegistry.register(TestRegistries.TEST_ENTITY, CowRenderer::new); EntityRendererRegistry.register(TestRegistries.TEST_ENTITY_2, CowRenderer::new); ClientTooltipComponentRegistry.register(ItemWithTooltip.MyTooltipComponent.class, ItemWithTooltip.MyClientTooltipComponent::new); + ClientCommandRegistrationEvent.EVENT.register((dispatcher, access) -> { + dispatcher.register(ClientCommandRegistrationEvent.literal("cool_client") + .then(ClientCommandRegistrationEvent.argument("string", StringArgumentType.string()) + .executes(context -> { + String string = StringArgumentType.getString(context, "string"); + SINK.accept("Cool client command for " + string); + return 0; + }))); + }); } } } From cd74016d85b562affb21890cb8796b1e34ac2ca9 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Mon, 26 Feb 2024 22:10:17 +0900 Subject: [PATCH 2/2] Bump version for release Signed-off-by: shedaniel --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6fcf751a7..da279762d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ artifact_type=release archives_base_name=architectury archives_base_name_snapshot=architectury-snapshot -base_version=6.5 +base_version=6.6 maven_group=dev.architectury fabric_loader_version=0.14.19