From 6a084781ba5ea317dd4aa3880bde879d48a48387 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Tue, 29 Oct 2024 17:22:25 +0800 Subject: [PATCH 01/16] docs: update connector env --- docs/chapters/qna/qna.tex | 10 +++++----- docs/release/fuji.pdf | Bin 460322 -> 460564 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/chapters/qna/qna.tex b/docs/chapters/qna/qna.tex index 8b144120..3e4f00d5 100644 --- a/docs/chapters/qna/qna.tex +++ b/docs/chapters/qna/qna.tex @@ -52,13 +52,13 @@ \LevelOne{Can I ask the forge or neoforge support?} We have no plan for forge or neoforge platform.However, you can try running this mod via \tbf{sinytra-connector} mod. -It's tested the mod works in the following environment (104/104 modules works): +It's tested the mod works in the following environment (105/105 modules works): \begin{shcode} - Loader: NeoForge v21.0.167 for Minecraft 1.21 + Loader: NeoForge v21.1.73:server for Minecraft 1.21.1 Mods: - - connector-2.0.0-beta.1+1.21-full - - forgified-fabric-api-0.101.2+2.0.10+1.21 - - fuji-1.6.3-release-1914a82a84 + - connector-2.0.0-beta.3+1.21.1-full.jar + - forgified-fabric-api-0.104.0+2.0.15+1.21.1.jar + - fuji-4.3.0-5518b05201-mc1.21.jar \end{shcode} \LevelOne{How can I report bugs or suggest new features?} diff --git a/docs/release/fuji.pdf b/docs/release/fuji.pdf index 12a62bb86910597c74cb3529de1c5637bd23cb13..7bc6cd00a640e24429aae7e4e49f6e13ae5d30bb 100644 GIT binary patch delta 29349 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 delta 29112 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 cdWG`)pdt!Bf=3`n;S> Date: Wed, 30 Oct 2024 14:53:10 +0800 Subject: [PATCH 02/16] feature: add @CommandTarget annotation + retarget command descriptor --- TODO.md | 3 +- .../command/annotation/CommandTarget.java | 8 + .../PlayerCollectionArgumentTypeAdapter.java | 35 +++++ .../wrapper/impl/PlayerCollection.java | 12 ++ .../processor/CommandAnnotationProcessor.java | 4 + .../command/structure/CommandDescriptor.java | 4 +- .../structure/RetargetCommandDescriptor.java | 138 ++++++++++++++++++ .../command_toolbox/heal/HealInitializer.java | 14 +- .../auxiliary/argument-type-adapter-graph.txt | 1 + 9 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 src/main/java/io/github/sakurawald/core/command/annotation/CommandTarget.java create mode 100644 src/main/java/io/github/sakurawald/core/command/argument/adapter/impl/PlayerCollectionArgumentTypeAdapter.java create mode 100644 src/main/java/io/github/sakurawald/core/command/argument/wrapper/impl/PlayerCollection.java create mode 100644 src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java diff --git a/TODO.md b/TODO.md index 1cfb3f57..90c064aa 100644 --- a/TODO.md +++ b/TODO.md @@ -24,5 +24,4 @@ - list operations - json operations - text operation - - application: /air, /alert, /respawn, /vote -- feature: add @CommandTarget annotation \ No newline at end of file + - application: /air, /alert, /respawn, /vote \ No newline at end of file diff --git a/src/main/java/io/github/sakurawald/core/command/annotation/CommandTarget.java b/src/main/java/io/github/sakurawald/core/command/annotation/CommandTarget.java new file mode 100644 index 00000000..ed2afc00 --- /dev/null +++ b/src/main/java/io/github/sakurawald/core/command/annotation/CommandTarget.java @@ -0,0 +1,8 @@ +package io.github.sakurawald.core.command.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface CommandTarget { +} diff --git a/src/main/java/io/github/sakurawald/core/command/argument/adapter/impl/PlayerCollectionArgumentTypeAdapter.java b/src/main/java/io/github/sakurawald/core/command/argument/adapter/impl/PlayerCollectionArgumentTypeAdapter.java new file mode 100644 index 00000000..7985ebe6 --- /dev/null +++ b/src/main/java/io/github/sakurawald/core/command/argument/adapter/impl/PlayerCollectionArgumentTypeAdapter.java @@ -0,0 +1,35 @@ +package io.github.sakurawald.core.command.argument.adapter.impl; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import io.github.sakurawald.core.command.argument.adapter.abst.BaseArgumentTypeAdapter; +import io.github.sakurawald.core.command.argument.structure.Argument; +import io.github.sakurawald.core.command.argument.wrapper.impl.PlayerCollection; +import lombok.SneakyThrows; +import net.minecraft.command.argument.EntityArgumentType; +import net.minecraft.server.command.ServerCommandSource; + +import java.util.List; + +public class PlayerCollectionArgumentTypeAdapter extends BaseArgumentTypeAdapter { + @Override + protected ArgumentType makeArgumentType() { + return EntityArgumentType.players(); + } + + @SneakyThrows + @Override + protected Object makeArgumentObject(CommandContext context, Argument argument) { + return new PlayerCollection(EntityArgumentType.getPlayers(context, argument.getArgumentName())); + } + + @Override + public List> getTypeClasses() { + return List.of(PlayerCollection.class); + } + + @Override + public List getTypeStrings() { + return List.of("players", "player-list"); + } +} diff --git a/src/main/java/io/github/sakurawald/core/command/argument/wrapper/impl/PlayerCollection.java b/src/main/java/io/github/sakurawald/core/command/argument/wrapper/impl/PlayerCollection.java new file mode 100644 index 00000000..e8dcda15 --- /dev/null +++ b/src/main/java/io/github/sakurawald/core/command/argument/wrapper/impl/PlayerCollection.java @@ -0,0 +1,12 @@ +package io.github.sakurawald.core.command.argument.wrapper.impl; + +import io.github.sakurawald.core.command.argument.wrapper.abst.SingularValue; +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.Collection; + +public class PlayerCollection extends SingularValue> { + public PlayerCollection(Collection value) { + super(value); + } +} diff --git a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java index b6ec1c24..e877e2b4 100644 --- a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java +++ b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java @@ -11,6 +11,7 @@ import io.github.sakurawald.core.command.argument.structure.Argument; import io.github.sakurawald.core.command.structure.CommandDescriptor; import io.github.sakurawald.core.command.structure.CommandRequirementDescriptor; +import io.github.sakurawald.core.command.structure.RetargetCommandDescriptor; import io.github.sakurawald.core.event.impl.CommandEvents; import io.github.sakurawald.core.manager.Managers; import lombok.Getter; @@ -94,6 +95,9 @@ private static void processMethod(Class clazz, Method method) { /* register the command descriptor */ descriptor.register(); + + RetargetCommandDescriptor.make(descriptor) + .ifPresent(CommandDescriptor::register); } private static Class unbox(Parameter parameter) { diff --git a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java index ec541160..93c44361 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java @@ -277,7 +277,9 @@ protected List makeCommandFunctionArgs(CommandContext arguments, int commandTargetAnnotationIndex) { + super(method, arguments); + this.commandTargetAnnotationIndex = commandTargetAnnotationIndex; + } + + private static CommandRequirementDescriptor deriveCommandRequirementForInsertPoint(List arguments, int insertIndex) { + /* try to copy the requirement from next level */ + if (insertIndex < arguments.size()) { + return arguments.get(insertIndex).getRequirement(); + } + + /* try to copy the requirement from prev level */ + return arguments.getLast().getRequirement(); + } + + private static List insertOthersArguments(List arguments) { + List ret = new ArrayList<>(arguments); + + for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { + Argument argument = arguments.get(argumentIndex); + + /* ensure the `others` args are the `first required argument`, so that the `makeCommandFunctionArgs()` can extract the targets in the first arg */ + if (argument.isRequiredArgument() || argumentIndex == ret.size() - 1) { + + /* all retarget commands require level 4 permission to use */ + CommandRequirementDescriptor requirement = new CommandRequirementDescriptor(4, null); + + ret.add(argumentIndex, Argument.makeLiteralArgument("others", requirement)); + ret.add(argumentIndex + 1, Argument.makeRequiredArgument(PlayerCollection.class, "others", COMMAND_TARGET_DUMMY_PARAMETER_INDEX, false, requirement)); + break; + } + + } + + return ret; + } + + private static Optional findCommandTargetAnnotationIndex(Method method) { + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + if (parameter.isAnnotationPresent(CommandTarget.class)) { + return Optional.of(i); + } + } + + return Optional.empty(); + } + + @Override + protected Command makeCommandFunctionClosure() { + return (ctx) -> { + + /* verify command source */ + if (!verifyCommandSource(ctx, this)) { + return CommandHelper.Return.FAIL; + } + + LogUtil.debug("execute retarget command: initialing command source = {}", ctx.getSource().getName()); + + /* invoke the command function */ + List args = makeCommandFunctionArgs(ctx); + + /* apply the command execution for each target. */ + PlayerCollection targets = (PlayerCollection) args.getFirst(); + LogUtil.debug("unbox the first argument and get the targets: {}", targets.getValue().stream().map(it -> it.getGameProfile().getName()).toList()); + + int totalValue = CommandHelper.Return.SUCCESS; + for (ServerPlayerEntity target : targets.getValue()) { + + List unboxedArgs = args.subList(1, args.size()); + unboxedArgs.set(this.commandTargetAnnotationIndex, target); + + LogUtil.debug("invoke command method {} in class {}: target = {}, args = {}" + , this.method.getName() + , this.method.getDeclaringClass().getSimpleName() + , target.getGameProfile().getName() + , unboxedArgs); + + try { + // if one of the execution if failed, then it's considered the whole return value is failed. + int singleValue = (int) this.method.invoke(null, unboxedArgs.toArray()); + + if (singleValue != CommandHelper.Return.SUCCESS) { + totalValue = CommandHelper.Return.FAIL; + } + + } catch (Exception wrappedOrUnwrappedException) { + return handleException(ctx, this.method, wrappedOrUnwrappedException); + } + } + + return totalValue; + }; + } + + public static Optional make(CommandDescriptor commandDescriptor) { + + /* filter */ + Optional commandTargetAnnotationIndexOpt = findCommandTargetAnnotationIndex(commandDescriptor.method); + if (commandTargetAnnotationIndexOpt.isEmpty()) { + return Optional.empty(); + } + int commandTargetAnnotationIndex = commandTargetAnnotationIndexOpt.get(); + + /* make retarget command descriptor */ + Method delegateMethod = commandDescriptor.getMethod(); + List argsWithOthers = insertOthersArguments(commandDescriptor.getArguments()); + + RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(delegateMethod, argsWithOthers, commandTargetAnnotationIndex); + + return Optional.of(retargetCommandDescriptor); + } + +} diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/heal/HealInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/heal/HealInitializer.java index 04b6e85c..b9ed3ad3 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/heal/HealInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/heal/HealInitializer.java @@ -5,24 +5,18 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; -import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; public class HealInitializer extends ModuleInitializer { - - @CommandNode("heal") - private static int $heal(@CommandSource ServerPlayerEntity player) { - return $heal(player.getCommandSource(), player); - } - @CommandNode("heal") @CommandRequirement(level = 4) - private static int $heal(@CommandSource ServerCommandSource source, ServerPlayerEntity target) { - target.setHealth(target.getMaxHealth()); - TextHelper.sendMessageByKey(target, "heal"); + private static int $heal(@CommandSource @CommandTarget ServerPlayerEntity player) { + player.setHealth(player.getMaxHealth()); + TextHelper.sendMessageByKey(player, "heal"); return CommandHelper.Return.SUCCESS; } diff --git a/src/main/resources/io/github/sakurawald/core/auxiliary/argument-type-adapter-graph.txt b/src/main/resources/io/github/sakurawald/core/auxiliary/argument-type-adapter-graph.txt index e39a83dd..35198d9b 100644 --- a/src/main/resources/io/github/sakurawald/core/auxiliary/argument-type-adapter-graph.txt +++ b/src/main/resources/io/github/sakurawald/core/auxiliary/argument-type-adapter-graph.txt @@ -33,6 +33,7 @@ io.github.sakurawald.core.command.argument.adapter.impl.OfflinePlayerArgumentTyp io.github.sakurawald.core.command.argument.adapter.impl.OperationArgumentTypeAdapter io.github.sakurawald.core.command.argument.adapter.impl.ParticleEffectArgumentTypeAdapter io.github.sakurawald.core.command.argument.adapter.impl.PlayerArgumentTypeAdapter +io.github.sakurawald.core.command.argument.adapter.impl.PlayerCollectionArgumentTypeAdapter io.github.sakurawald.core.command.argument.adapter.impl.RotationArgumentTypeAdapter io.github.sakurawald.core.command.argument.adapter.impl.ScoreboardCriterionArgumentTypeAdapter io.github.sakurawald.core.command.argument.adapter.impl.ScoreboardObjectiveArgumentTypeAdapter From 15ec4b21e913bee99ac3eb4a2730d1d4a06f4984 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 16:23:26 +0800 Subject: [PATCH 03/16] feature: add @CommandTarget annotation for: all functional commands, most toolbox commands, other commands --- .../structure/RetargetCommandDescriptor.java | 60 ++++++++++++------- .../initializer/afk/AfkInitializer.java | 3 +- .../initializer/back/BackInitializer.java | 3 +- .../chat/style/ChatStyleInitializer.java | 5 +- .../command_toolbox/bed/BedInitializer.java | 3 +- .../compass/CompassInitializer.java | 7 ++- .../extinguish/ExtinguishInitializer.java | 3 +- .../command_toolbox/feed/FeedInitializer.java | 13 ++-- .../command_toolbox/fly/FlyInitializer.java | 3 +- .../command_toolbox/glow/GlowInitializer.java | 3 +- .../command_toolbox/god/GodInitializer.java | 3 +- .../command_toolbox/hat/HatInitializer.java | 3 +- .../command_toolbox/jump/JumpInitializer.java | 3 +- .../nickname/NicknameInitializer.java | 5 +- .../repair/RepairInitializer.java | 3 +- .../command_toolbox/sit/SitInitializer.java | 3 +- .../command_toolbox/top/TopInitializer.java | 3 +- .../trashcan/TrashCanInitializer.java | 3 +- .../command_toolbox/warp/WarpInitializer.java | 3 +- .../functional/anvil/AnvilInitializer.java | 3 +- .../cartography/CartographyInitializer.java | 3 +- .../enchantment/EnchantmentInitializer.java | 3 +- .../enderchest/EnderChestInitializer.java | 3 +- .../grindstone/GrindStoneInitializer.java | 3 +- .../functional/loom/LoomInitializer.java | 3 +- .../functional/smithing/SmithInitializer.java | 3 +- .../stonecutter/StoneCutterInitializer.java | 3 +- .../workbench/WorkbenchInitializer.java | 3 +- .../initializer/pvp/PvpInitializer.java | 7 ++- .../initializer/rtp/RtpInitializer.java | 3 +- 30 files changed, 105 insertions(+), 64 deletions(-) diff --git a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java index 3021ad9a..6245ea32 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java @@ -26,18 +26,18 @@ private RetargetCommandDescriptor(Method method, List arguments, int c this.commandTargetAnnotationIndex = commandTargetAnnotationIndex; } - private static CommandRequirementDescriptor deriveCommandRequirementForInsertPoint(List arguments, int insertIndex) { - /* try to copy the requirement from next level */ - if (insertIndex < arguments.size()) { - return arguments.get(insertIndex).getRequirement(); - } - - /* try to copy the requirement from prev level */ - return arguments.getLast().getRequirement(); - } - - private static List insertOthersArguments(List arguments) { - List ret = new ArrayList<>(arguments); + private static List transformWithOthersArguments(List arguments, int commandTargetAnnotationIndex) { + List ret = new ArrayList<>(arguments + .stream() + .filter(it -> + /* + remove the argument that is annotated with @CommandTarget and is not annotated with @CommandSource, + so that this argument will not be registered in the command tree. + */ + it.isCommandSource() || + it.getMethodParameterIndex() != commandTargetAnnotationIndex + ) + .toList()); for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { Argument argument = arguments.get(argumentIndex); @@ -63,6 +63,11 @@ private static Optional findCommandTargetAnnotationIndex(Method method) for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; if (parameter.isAnnotationPresent(CommandTarget.class)) { + // verify + if (!parameter.getType().equals(ServerPlayerEntity.class)) { + throw new IllegalArgumentException("the annotation @CommandTarget can only be used in a parameter whose type is ServerPlayerEntity: class = %s, method = %s".formatted(method.getDeclaringClass().getSimpleName(), method.getName())); + } + return Optional.of(i); } } @@ -88,11 +93,22 @@ protected Command makeCommandFunctionClosure() { PlayerCollection targets = (PlayerCollection) args.getFirst(); LogUtil.debug("unbox the first argument and get the targets: {}", targets.getValue().stream().map(it -> it.getGameProfile().getName()).toList()); - int totalValue = CommandHelper.Return.SUCCESS; + int finalValue = CommandHelper.Return.SUCCESS; for (ServerPlayerEntity target : targets.getValue()) { List unboxedArgs = args.subList(1, args.size()); - unboxedArgs.set(this.commandTargetAnnotationIndex, target); + /* + if the @CommandSource and @CommandTarget are both annotated in the same parameter: + 1. The @CommandSource will still be used to verify the type of `initialing command source`. + 2. After that, the command source passed to the command method will be overridden by the @CommandTarget. + 3. Any exceptions thrown during the execution of the command method, will be reported to the `initialing command source`. + */ + if (this.commandTargetAnnotationIndex < unboxedArgs.size()) { + unboxedArgs.set(this.commandTargetAnnotationIndex, target); + } else { + // if the commandTargetAnnotationIndex < unboxedArgs, then it means the argument annotated with @CommandTarget is filtered. + unboxedArgs.add(this.commandTargetAnnotationIndex, target); + } LogUtil.debug("invoke command method {} in class {}: target = {}, args = {}" , this.method.getName() @@ -103,9 +119,13 @@ protected Command makeCommandFunctionClosure() { try { // if one of the execution if failed, then it's considered the whole return value is failed. int singleValue = (int) this.method.invoke(null, unboxedArgs.toArray()); + LogUtil.debug("the return value of command method is {}: target = {}, args = {}" + , singleValue + , target.getGameProfile().getName() + , unboxedArgs); if (singleValue != CommandHelper.Return.SUCCESS) { - totalValue = CommandHelper.Return.FAIL; + finalValue = CommandHelper.Return.FAIL; } } catch (Exception wrappedOrUnwrappedException) { @@ -113,13 +133,12 @@ protected Command makeCommandFunctionClosure() { } } - return totalValue; + return finalValue; }; } public static Optional make(CommandDescriptor commandDescriptor) { - - /* filter */ + /* filter: the method that contains @CommandTarget */ Optional commandTargetAnnotationIndexOpt = findCommandTargetAnnotationIndex(commandDescriptor.method); if (commandTargetAnnotationIndexOpt.isEmpty()) { return Optional.empty(); @@ -128,10 +147,9 @@ public static Optional make(CommandDescriptor command /* make retarget command descriptor */ Method delegateMethod = commandDescriptor.getMethod(); - List argsWithOthers = insertOthersArguments(commandDescriptor.getArguments()); - - RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(delegateMethod, argsWithOthers, commandTargetAnnotationIndex); + List transformedArgs = transformWithOthersArguments(commandDescriptor.getArguments(), commandTargetAnnotationIndex); + RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(delegateMethod, transformedArgs, commandTargetAnnotationIndex); return Optional.of(retargetCommandDescriptor); } diff --git a/src/main/java/io/github/sakurawald/module/initializer/afk/AfkInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/afk/AfkInitializer.java index 4f9e0d84..074c07d9 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/afk/AfkInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/afk/AfkInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; import io.github.sakurawald.core.event.impl.ServerLifecycleEvents; @@ -33,7 +34,7 @@ public class AfkInitializer extends ModuleInitializer { // note: issue command will update lastLastActionTime, so it's impossible to use /afk to disable afk @CommandNode("afk") @Document("Enter afk state.") - private static int $afk(@CommandSource ServerPlayerEntity player) { + private static int $afk(@CommandSource @CommandTarget ServerPlayerEntity player) { if (!player.isOnGround() || player.isOnFire() || player.inPowderSnow diff --git a/src/main/java/io/github/sakurawald/module/initializer/back/BackInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/back/BackInitializer.java index c8168361..b8374204 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/back/BackInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/back/BackInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; import io.github.sakurawald.core.structure.SpatialPose; @@ -25,7 +26,7 @@ public class BackInitializer extends ModuleInitializer { @CommandNode("back") @Document("Back to the recent death location or recent teleport location.") - private static int $back(@CommandSource ServerPlayerEntity player) { + private static int $back(@CommandSource @CommandTarget ServerPlayerEntity player) { SpatialPose lastPos = player2lastPos.get(player.getName().getString()); if (lastPos == null) { TextHelper.sendActionBarByKey(player, "back.no_previous_position"); diff --git a/src/main/java/io/github/sakurawald/module/initializer/chat/style/ChatStyleInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/chat/style/ChatStyleInitializer.java index 1f7fa909..0d3b9ef8 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/chat/style/ChatStyleInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/chat/style/ChatStyleInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.GreedyString; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; @@ -43,7 +44,7 @@ public class ChatStyleInitializer extends ModuleInitializer { .build(); @CommandNode("set") - private static int setPlayerFormat(@CommandSource ServerPlayerEntity player, GreedyString format) { + private static int setPlayerFormat(@CommandSource @CommandTarget ServerPlayerEntity player, GreedyString format) { /* save the format*/ String name = player.getGameProfile().getName(); String $format = format.getValue(); @@ -60,7 +61,7 @@ private static int setPlayerFormat(@CommandSource ServerPlayerEntity player, Gre } @CommandNode("reset") - private static int resetPlayerFormat(@CommandSource ServerPlayerEntity player) { + private static int resetPlayerFormat(@CommandSource @CommandTarget ServerPlayerEntity player) { String name = player.getGameProfile().getName(); chat.model().format.player2format.remove(name); chat.writeStorage(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/bed/BedInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/bed/BedInitializer.java index 6f601aea..de867ce2 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/bed/BedInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/bed/BedInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.structure.SpatialPose; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.registry.RegistryKey; @@ -19,7 +20,7 @@ public class BedInitializer extends ModuleInitializer { @CommandNode("bed") @Document("Teleport to the bed location.") - private static int $bed(@CommandSource ServerPlayerEntity player) { + private static int $bed(@CommandSource @CommandTarget ServerPlayerEntity player) { BlockPos respawnPosition = player.getSpawnPointPosition(); RegistryKey respawnDimension = player.getSpawnPointDimension(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/compass/CompassInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/compass/CompassInitializer.java index dc9f1b61..83901467 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/compass/CompassInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/compass/CompassInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.Dimension; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.component.DataComponentTypes; @@ -39,7 +40,7 @@ private static void setTrackedTarget(ItemStack itemStack, ServerWorld world, Blo @CommandNode("track pos") @Document("Let the compass in hand track a specified position.") - private static int track(@CommandSource ServerPlayerEntity player, Dimension dimension, BlockPos blockPos) { + private static int track(@CommandSource @CommandTarget ServerPlayerEntity player, Dimension dimension, BlockPos blockPos) { return withCompassInHand(player, (itemStack) -> { setTrackedTarget(itemStack, dimension.getValue(), blockPos); return CommandHelper.Return.SUCCESS; @@ -48,7 +49,7 @@ private static int track(@CommandSource ServerPlayerEntity player, Dimension dim @CommandNode("track player") @Document("Let the compass in hand track a specified player.") - private static int track(@CommandSource ServerPlayerEntity player, ServerPlayerEntity target) { + private static int track(@CommandSource @CommandTarget ServerPlayerEntity player, ServerPlayerEntity target) { return withCompassInHand(player, (itemStack) -> { setTrackedTarget(itemStack, target.getServerWorld(), target.getBlockPos()); return CommandHelper.Return.SUCCESS; @@ -57,7 +58,7 @@ private static int track(@CommandSource ServerPlayerEntity player, ServerPlayerE @CommandNode("reset") @Document("Let the compass in hand track nothing.") - private static int reset(@CommandSource ServerPlayerEntity player) { + private static int reset(@CommandSource @CommandTarget ServerPlayerEntity player) { return withCompassInHand(player, (itemStack) -> { itemStack.set(DataComponentTypes.LODESTONE_TRACKER, null); return CommandHelper.Return.SUCCESS; diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java index 8cf4b4f4..c1cc4e67 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java @@ -4,6 +4,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -13,7 +14,7 @@ public class ExtinguishInitializer extends ModuleInitializer { @CommandNode("extinguish") @Document("Set fire ticks to 0.") - private static int $extinguish(@CommandSource ServerPlayerEntity player) { + private static int $extinguish(@CommandSource @CommandTarget ServerPlayerEntity player) { player.setFireTicks(0); return CommandHelper.Return.SUCCESS; } diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/feed/FeedInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/feed/FeedInitializer.java index 8056e847..473db67e 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/feed/FeedInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/feed/FeedInitializer.java @@ -6,9 +6,9 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.HungerManager; -import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; @@ -16,18 +16,13 @@ public class FeedInitializer extends ModuleInitializer { @CommandNode("feed") @Document("Set food level, saturation level and exhaustion to healthy state.") - private static int $feed(@CommandSource ServerPlayerEntity player) { - return $feed(player.getCommandSource(), player); - } - - @CommandNode("feed") @CommandRequirement(level = 4) - private static int $feed(@CommandSource ServerCommandSource source, ServerPlayerEntity target) { - HungerManager foodData = target.getHungerManager(); + private static int $feed(@CommandSource @CommandTarget ServerPlayerEntity source) { + HungerManager foodData = source.getHungerManager(); foodData.setFoodLevel(20); foodData.setSaturationLevel(5); - TextHelper.sendMessageByKey(target, "feed"); + TextHelper.sendMessageByKey(source, "feed"); return CommandHelper.Return.SUCCESS; } } diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/fly/FlyInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/fly/FlyInitializer.java index 8e43a678..4bf0e838 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/fly/FlyInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/fly/FlyInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -13,7 +14,7 @@ public class FlyInitializer extends ModuleInitializer { @CommandNode("fly") @CommandRequirement(level = 4) - private static int $fly(@CommandSource ServerPlayerEntity player) { + private static int $fly(@CommandSource @CommandTarget ServerPlayerEntity player) { boolean flag = !player.getAbilities().allowFlying; player.getAbilities().allowFlying = flag; diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/glow/GlowInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/glow/GlowInitializer.java index 5de39bfe..d4526140 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/glow/GlowInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/glow/GlowInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -13,7 +14,7 @@ public class GlowInitializer extends ModuleInitializer { @CommandNode("glow") @Document("Toggle the glowing state.") - private static int $glow(@CommandSource ServerPlayerEntity player) { + private static int $glow(@CommandSource @CommandTarget ServerPlayerEntity player) { boolean flag = !player.isGlowing(); player.setGlowing(flag); TextHelper.sendMessageByKey(player, flag ? "glow.on" : "glow.off"); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/god/GodInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/god/GodInitializer.java index e6a6c581..f328e50a 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/god/GodInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/god/GodInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -13,7 +14,7 @@ public class GodInitializer extends ModuleInitializer { @CommandNode("god") @CommandRequirement(level = 4) - private static int $god(@CommandSource ServerPlayerEntity player) { + private static int $god(@CommandSource @CommandTarget ServerPlayerEntity player) { boolean flag = !player.getAbilities().invulnerable; player.getAbilities().invulnerable = flag; player.sendAbilitiesUpdate(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/hat/HatInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/hat/HatInitializer.java index 86614c7e..f2142d0b 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/hat/HatInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/hat/HatInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.EquipmentSlot; import net.minecraft.item.ItemStack; @@ -16,7 +17,7 @@ public class HatInitializer extends ModuleInitializer { @CommandNode("hat") @Document("Wear the item in hand.") - private static int $hat(@CommandSource ServerPlayerEntity player) { + private static int $hat(@CommandSource @CommandTarget ServerPlayerEntity player) { ItemStack mainHandItem = player.getMainHandStack(); ItemStack headSlotItem = player.getEquippedStack(EquipmentSlot.HEAD); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/jump/JumpInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/jump/JumpInitializer.java index 193ce4f1..fc13a913 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/jump/JumpInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/jump/JumpInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.structure.SpatialPose; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -18,7 +19,7 @@ public class JumpInitializer extends ModuleInitializer { @CommandNode("jump") @CommandRequirement(level = 4) @Document("Jump to the position looking at.") - private static int jump(@CommandSource ServerPlayerEntity player + private static int jump(@CommandSource @CommandTarget ServerPlayerEntity player , @Document("The max distance to jump.") Optional distance) { int $distance = distance.orElse(128); HitResult raycast = player.raycast($distance, 0, false); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/nickname/NicknameInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/nickname/NicknameInitializer.java index ec7b230f..e5120f6e 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/nickname/NicknameInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/nickname/NicknameInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.GreedyString; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; @@ -28,7 +29,7 @@ private static String transformNickname(String string) { @CommandNode("set") @Document("Set the display name.") - private static int $set(@CommandSource ServerPlayerEntity player, GreedyString format) { + private static int $set(@CommandSource @CommandTarget ServerPlayerEntity player, GreedyString format) { String name = player.getGameProfile().getName(); String value = format.getValue(); @@ -44,7 +45,7 @@ private static String transformNickname(String string) { @CommandNode("reset") @Document("Clear the display name.") - private static int $reset(@CommandSource ServerPlayerEntity player) { + private static int $reset(@CommandSource @CommandTarget ServerPlayerEntity player) { String name = player.getGameProfile().getName(); data.model().format.player2format.remove(name); data.writeStorage(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/repair/RepairInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/repair/RepairInitializer.java index 236e3651..8f6f542a 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/repair/RepairInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/repair/RepairInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -15,7 +16,7 @@ public class RepairInitializer extends ModuleInitializer { @CommandNode("repair") @CommandRequirement(level = 4) @Document("Repair the item in hand.") - private static int $repair(@CommandSource ServerPlayerEntity player) { + private static int $repair(@CommandSource @CommandTarget ServerPlayerEntity player) { player.getMainHandStack().setDamage(0); TextHelper.sendMessageByKey(player, "repair"); return CommandHelper.Return.SUCCESS; diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/sit/SitInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/sit/SitInitializer.java index 2264171a..633ad52d 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/sit/SitInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/sit/SitInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; import io.github.sakurawald.core.event.impl.ServerLifecycleEvents; @@ -52,7 +53,7 @@ public static boolean canSit(ServerPlayerEntity player) { @SuppressWarnings("deprecation") @CommandNode("sit") @Document("Sit in current position.") - private static int $sit(@CommandSource ServerPlayerEntity player) { + private static int $sit(@CommandSource @CommandTarget ServerPlayerEntity player) { // fix: if the player stand in the slab/stair block BlockPos steppingBlockPos = player.getSteppingPos(); BlockState steppingBlockState = player.getWorld().getBlockState(steppingBlockPos); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/top/TopInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/top/TopInitializer.java index eec8f78d..7e9ca0a8 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/top/TopInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/top/TopInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.structure.SpatialPose; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.network.ServerPlayerEntity; @@ -16,7 +17,7 @@ public class TopInitializer extends ModuleInitializer { @CommandNode("top") @Document("Teleport to the top of your current position.") - private static int top(@CommandSource ServerPlayerEntity player) { + private static int top(@CommandSource @CommandTarget ServerPlayerEntity player) { World world = player.getWorld(); BlockPos topPosition = world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, player.getBlockPos()); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/trashcan/TrashCanInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/trashcan/TrashCanInitializer.java index d6b5ca66..8a0316e6 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/trashcan/TrashCanInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/trashcan/TrashCanInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.inventory.SimpleInventory; import net.minecraft.screen.GenericContainerScreenHandler; @@ -17,7 +18,7 @@ public class TrashCanInitializer extends ModuleInitializer { @CommandNode("trashcan") @Document("Open a trans can gui.") - private static int $trashcan(@CommandSource ServerPlayerEntity player) { + private static int $trashcan(@CommandSource @CommandTarget ServerPlayerEntity player) { int rows = 3; SimpleInventory simpleInventory = new SimpleInventory(rows * 9); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/warp/WarpInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/warp/WarpInitializer.java index 48ce4c48..611574bc 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/warp/WarpInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/warp/WarpInitializer.java @@ -7,6 +7,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.GreedyString; import io.github.sakurawald.core.command.exception.AbortCommandExecutionException; import io.github.sakurawald.core.command.executor.CommandExecutor; @@ -58,7 +59,7 @@ public static void doWarp(WarpNode warpNode, ServerPlayerEntity player) { } @CommandNode("tp") - private static int $tp(@CommandSource ServerPlayerEntity player, WarpName warpName) { + private static int $tp(@CommandSource @CommandTarget ServerPlayerEntity player, WarpName warpName) { return withWarpNode(player, warpName, warpNode -> { doWarp(warpNode, player); return CommandHelper.Return.SUCCESS; diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java index 895d331e..19d79643 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.AnvilScreenHandler; @@ -15,7 +16,7 @@ public class AnvilInitializer extends ModuleInitializer { @CommandNode("anvil") - private static int $anvil(@CommandSource ServerPlayerEntity player) { + private static int $anvil(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new AnvilScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java index 04b61f3b..4bb47de0 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.CartographyTableScreenHandler; @@ -14,7 +15,7 @@ public class CartographyInitializer extends ModuleInitializer { @CommandNode("cartography") - private static int $cartography(@CommandSource ServerPlayerEntity player) { + private static int $cartography(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new CartographyTableScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java index b17f6e7d..7940fcba 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -18,7 +19,7 @@ public class EnchantmentInitializer extends ModuleInitializer { public static final BaseConfigurationHandler config = new ObjectConfigurationHandler<>(BaseConfigurationHandler.CONFIG_JSON, EnchantmentConfigModel.class); @CommandNode("enchantment") - private static int $enchantment(@CommandSource ServerPlayerEntity player) { + private static int $enchantment(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new MyEnchantmentScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { }, Text.translatable("container.enchant"))); return CommandHelper.Return.SUCCESS; diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java index 0ae121c9..5c971183 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.inventory.EnderChestInventory; import net.minecraft.screen.GenericContainerScreenHandler; @@ -15,7 +16,7 @@ public class EnderChestInitializer extends ModuleInitializer { @CommandNode("enderchest") - private static int $enderchest(@CommandSource ServerPlayerEntity player) { + private static int $enderchest(@CommandSource @CommandTarget ServerPlayerEntity player) { EnderChestInventory enderChestInventory = player.getEnderChestInventory(); player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> GenericContainerScreenHandler.createGeneric9x3(i, inventory, enderChestInventory), Text.translatable("container.enderchest"))); player.incrementStat(Stats.OPEN_ENDERCHEST); diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java index 3624dccb..68c358f8 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.GrindstoneScreenHandler; @@ -15,7 +16,7 @@ public class GrindStoneInitializer extends ModuleInitializer { @CommandNode("grindstone") - private static int $grindstone(@CommandSource ServerPlayerEntity player) { + private static int $grindstone(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new GrindstoneScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java index 0e12c543..085c6474 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.LoomScreenHandler; @@ -15,7 +16,7 @@ public class LoomInitializer extends ModuleInitializer { @CommandNode("loom") - private static int $loom(@CommandSource ServerPlayerEntity player) { + private static int $loom(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new LoomScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java index 29348f4a..ee0a69d4 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.ScreenHandlerContext; @@ -15,7 +16,7 @@ public class SmithInitializer extends ModuleInitializer { @CommandNode("smithing") - private static int $smithing(@CommandSource ServerPlayerEntity player) { + private static int $smithing(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new SmithingScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java index 6b011c34..1ad856e2 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.ScreenHandlerContext; @@ -15,7 +16,7 @@ public class StoneCutterInitializer extends ModuleInitializer { @CommandNode("stonecutter") - private static int $stonecutter(@CommandSource ServerPlayerEntity player) { + private static int $stonecutter(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new StonecutterScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java index 43cc9519..e6e2ffe5 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.screen.CraftingScreenHandler; @@ -15,7 +16,7 @@ public class WorkbenchInitializer extends ModuleInitializer { @CommandNode("workbench") - private static int $workbench(@CommandSource ServerPlayerEntity player) { + private static int $workbench(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new CraftingScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override public boolean canUse(PlayerEntity player) { diff --git a/src/main/java/io/github/sakurawald/module/initializer/pvp/PvpInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/pvp/PvpInitializer.java index e2770ed2..d8860f31 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/pvp/PvpInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/pvp/PvpInitializer.java @@ -4,6 +4,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; import io.github.sakurawald.core.config.handler.impl.ObjectConfigurationHandler; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -19,7 +20,7 @@ public class PvpInitializer extends ModuleInitializer { private static final BaseConfigurationHandler pvpHandler = new ObjectConfigurationHandler<>("pvp.json", PvPDataModel.class); @CommandNode("pvp on") - private static int $on(@CommandSource ServerPlayerEntity player) { + private static int $on(@CommandSource @CommandTarget ServerPlayerEntity player) { Set whitelist = pvpHandler.model().whitelist; String name = player.getGameProfile().getName(); if (!whitelist.contains(name)) { @@ -35,7 +36,7 @@ public class PvpInitializer extends ModuleInitializer { } @CommandNode("pvp off") - private static int $off(@CommandSource ServerPlayerEntity player) { + private static int $off(@CommandSource @CommandTarget ServerPlayerEntity player) { Set whitelist = pvpHandler.model().whitelist; String name = player.getGameProfile().getName(); if (whitelist.contains(name)) { @@ -51,7 +52,7 @@ public class PvpInitializer extends ModuleInitializer { } @CommandNode("pvp status") - private static int $status(@CommandSource ServerPlayerEntity player) { + private static int $status(@CommandSource @CommandTarget ServerPlayerEntity player) { Set whitelist = pvpHandler.model().whitelist; boolean flag = whitelist.contains(player.getGameProfile().getName()); diff --git a/src/main/java/io/github/sakurawald/module/initializer/rtp/RtpInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/rtp/RtpInitializer.java index 37706ed3..e4ff89b0 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/rtp/RtpInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/rtp/RtpInitializer.java @@ -6,6 +6,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.Dimension; import io.github.sakurawald.core.command.exception.AbortCommandExecutionException; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; @@ -40,7 +41,7 @@ public class RtpInitializer extends ModuleInitializer { @CommandNode("rtp") @Document("Random rtp in specified dimension.") - private static int $rtp(@CommandSource ServerPlayerEntity player, Optional dimension) { + private static int $rtp(@CommandSource @CommandTarget ServerPlayerEntity player, Optional dimension) { ServerWorld serverWorld = dimension.isPresent() ? dimension.get().getValue() : player.getServerWorld(); TeleportSetup setup = withTeleportSetup(player, serverWorld); From 0add87815c223639a682f8d5094a80c744438b8b Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 16:23:33 +0800 Subject: [PATCH 04/16] docs: command permission --- .../chapters/module/command_permission/command_permission.tex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/chapters/module/command_permission/command_permission.tex b/docs/chapters/module/command_permission/command_permission.tex index cf5456ad..6ccf6242 100644 --- a/docs/chapters/module/command_permission/command_permission.tex +++ b/docs/chapters/module/command_permission/command_permission.tex @@ -34,6 +34,10 @@ or \cmd{/fuji inspect server-commands} \end{tips} +\begin{warn}{Understand the parent permission node and its children node} + It's recommend to modify the \ttt{apply-sponge-implicit-wildcard} option to \ttt{false} in \ttt{luckperms.conf}, to control the \ttt{permission node} more fine-grained. +\end{warn} + \LevelTwo{Example} \begin{example}{Allow everyone to use \cmd{/gamemode} command} \cmd{/lp group default permission set fuji.permission.gamemode true} From 911eaa823a60300b52fee1fe864fa1c6ef217c28 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 18:13:58 +0800 Subject: [PATCH 05/16] refactor: remove the parameter index field in CommandDescriptor --- .../command/argument/structure/Argument.java | 82 ++++++++++-------- .../processor/CommandAnnotationProcessor.java | 39 ++++++--- .../command/structure/CommandDescriptor.java | 41 +++++---- .../CommandRequirementDescriptor.java | 20 +++-- .../structure/RetargetCommandDescriptor.java | 86 ++++++++----------- .../core/gui/CommandDescriptorGui.java | 6 +- .../CommandBundleInitializer.java | 2 +- .../structure/BundleCommandDescriptor.java | 10 +-- .../initializer/fuji/FujiInitializer.java | 2 +- src/test/java/tests/ArgumentMakerTest.java | 6 +- 10 files changed, 160 insertions(+), 134 deletions(-) diff --git a/src/main/java/io/github/sakurawald/core/command/argument/structure/Argument.java b/src/main/java/io/github/sakurawald/core/command/argument/structure/Argument.java index bf4455a8..0c213d2e 100644 --- a/src/main/java/io/github/sakurawald/core/command/argument/structure/Argument.java +++ b/src/main/java/io/github/sakurawald/core/command/argument/structure/Argument.java @@ -1,11 +1,16 @@ package io.github.sakurawald.core.command.argument.structure; import io.github.sakurawald.core.annotation.Document; +import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.structure.CommandRequirementDescriptor; import lombok.Getter; +import net.minecraft.server.network.ServerPlayerEntity; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.lang.reflect.Parameter; + /** * Rules: * - There are 2 kinds of Argument: LiteralArgument and RequiredArgument. @@ -16,35 +21,32 @@ */ @Getter public class Argument { - private static final String REQUIRED_ARGUMENT_PLACEHOLDER = "$"; private static final int THE_METHOD_PARAMETER_INDEX_FOR_LITERAL_ARGUMENT = -1; - final Class type; - final String argumentName; + final @Nullable Class type; + final @NotNull String argumentName; final boolean isOptional; - final CommandRequirementDescriptor requirement; - int methodParameterIndex; + final @Nullable CommandRequirementDescriptor requirement; boolean isCommandSource; + // this field is only used for RetargetCommandDescriptor + boolean isCommandTarget; + @Nullable String document; - private Argument(@Nullable Class type, @NotNull String argumentName, int methodParameterIndex, boolean isOptional, @Nullable CommandRequirementDescriptor requirement) { + private Argument(@Nullable Class type, @NotNull String argumentName, boolean isOptional, @Nullable CommandRequirementDescriptor requirement) { this.type = type; this.argumentName = argumentName; - this.methodParameterIndex = methodParameterIndex; this.isOptional = isOptional; this.requirement = requirement; - - // if it's a required argument placeholder... - this.methodParameterIndex = this.tryParseMethodParameterIndexFromArgumentName(); } - public static Argument makeRequiredArgument(@Nullable Class type, @NotNull String argumentName, int methodParameterIndex, boolean isOptional, @Nullable CommandRequirementDescriptor requirement) { - return new Argument(type, argumentName, methodParameterIndex, isOptional, requirement); + public static Argument makeRequiredArgument(@NotNull Class type, @NotNull String argumentName, boolean isOptional, @Nullable CommandRequirementDescriptor requirement) { + return new Argument(type, argumentName, isOptional, requirement); } public static Argument makeLiteralArgument(@NotNull String argumentName, @Nullable CommandRequirementDescriptor requirement) { - return new Argument(null, argumentName, THE_METHOD_PARAMETER_INDEX_FOR_LITERAL_ARGUMENT, false, requirement); + return new Argument(null, argumentName, false, requirement); } public Argument withDocument(@Nullable Document document) { @@ -55,18 +57,14 @@ public Argument withDocument(@Nullable Document document) { } public boolean isRequiredArgument() { - // A literal argument doesn't need to get the value from the parameter in the method. - // A required argument needs to get the value from the parameter in the method, so the index >= 0. - return this.methodParameterIndex >= 0; + // the type for literal argument is always null. + return this.type != null; } public boolean isLiteralArgument() { return !this.isRequiredArgument(); } - public boolean isRequiredArgumentPlaceholder() { - return this.argumentName.startsWith(REQUIRED_ARGUMENT_PLACEHOLDER); - } private String computeRequirementString() { if (this.requirement != null) { @@ -79,15 +77,16 @@ private String computeRequirementString() { @Override public String toString() { - // command source - String commandSourceString = this.isCommandSource ? "@" : ""; - /* required argument */ + String flags = ""; + if (this.isCommandSource) flags += "S"; + if (this.isCommandTarget) flags += "T"; + if (this.isRequiredArgument()) { if (isOptional) { - return commandSourceString + "[%s $%d]{%s}".formatted(this.argumentName, this.methodParameterIndex, this.computeRequirementString()); + return "[%s](%s){%s}".formatted(this.argumentName, flags, this.computeRequirementString()); } else { - return commandSourceString + "<%s $%d>{%s}".formatted(this.argumentName, this.methodParameterIndex, this.computeRequirementString()); + return "<%s>(%s){%s}".formatted(this.argumentName, flags, this.computeRequirementString()); } } @@ -95,11 +94,13 @@ public String toString() { return "%s{%s}".formatted(this.argumentName, this.computeRequirementString()); } - public String toInGameString() { + public String toHumanReadableString() { if (this.isLiteralArgument()) { return this.argumentName; } + // the type is only null if this is a literal argument. + assert this.getType() != null; if (isOptional) { return "[%s %s]".formatted(this.argumentName, this.getType().getSimpleName()); } else { @@ -107,23 +108,34 @@ public String toInGameString() { } } - private int tryParseMethodParameterIndexFromArgumentName() { - // parse the method parameter index - if (argumentName.startsWith(REQUIRED_ARGUMENT_PLACEHOLDER)) { - this.methodParameterIndex = Integer.parseInt(argumentName.substring(REQUIRED_ARGUMENT_PLACEHOLDER.length())); - } - - return methodParameterIndex; + public Argument markWithParameter(Parameter parameter) { + this.markAsCommandSourceWithParameter(parameter); + this.markAsCommandTargetWithParameter(parameter); + return this; } - public Argument markAsCommandSource() { + private Argument markAsCommandSourceWithParameter(Parameter parameter) { + if (!parameter.isAnnotationPresent(CommandSource.class)) return this; + if (!this.isRequiredArgument()) throw new IllegalArgumentException("The argument for command source must be a required argument."); - if (this.getType() == null) - throw new IllegalArgumentException("The type of the argument for command source must not null."); this.isCommandSource = true; return this; } + private Argument markAsCommandTargetWithParameter(Parameter parameter) { + if (!parameter.isAnnotationPresent(CommandTarget.class)) return this; + + if (!this.isRequiredArgument()) + throw new IllegalArgumentException("The argument for command target must be a required argument."); + + if (!parameter.getType().equals(ServerPlayerEntity.class)) { + throw new IllegalArgumentException("the annotation @CommandTarget can only be used in a parameter whose type is ServerPlayerEntity: class = %s, method = %s".formatted(parameter.getDeclaringExecutable().getName(), parameter.getDeclaringExecutable().getDeclaringClass().getSimpleName())); + } + + this.isCommandTarget = true; + return this; + } + } diff --git a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java index e877e2b4..ad555f50 100644 --- a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java +++ b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java @@ -37,6 +37,8 @@ }) public class CommandAnnotationProcessor { + private static final String REQUIRED_ARGUMENT_PLACEHOLDER = "$"; + /* yeah, this is a concurrent hash set. Be careful don't write the hashCode() for command descriptor, just use the memory address, use the command path to identify a command descriptor is possible to broken in some cases of register() and unregister(). @@ -109,6 +111,20 @@ private static Class unbox(Parameter parameter) { return parameter.getType(); } + private static boolean isRequiredArgumentPlaceholder(Argument argument) { + return argument.getArgumentName().startsWith(REQUIRED_ARGUMENT_PLACEHOLDER); + } + + private static int parseMethodParameterIndexFromArgumentName(Argument argument) { + // parse the method parameter index + String argumentName = argument.getArgumentName(); + if (argumentName.startsWith(REQUIRED_ARGUMENT_PLACEHOLDER)) { + return Integer.parseInt(argumentName.substring(REQUIRED_ARGUMENT_PLACEHOLDER.length())); + } + + throw new IllegalArgumentException("failed to parse parameter index from argument name for argument" + argument); + } + private static @NotNull CommandDescriptor makeCommandDescriptor(Class clazz, Method method) { List argumentList = new ArrayList<>(); @@ -147,21 +163,22 @@ private static Class unbox(Parameter parameter) { } /* process the required arguments */ - boolean hasAnyRequiredArgumentPlaceholder = argumentList.stream().anyMatch(Argument::isRequiredArgumentPlaceholder); + boolean hasAnyRequiredArgumentPlaceholder = argumentList.stream().anyMatch(CommandAnnotationProcessor::isRequiredArgumentPlaceholder); if (hasAnyRequiredArgumentPlaceholder) { /* specify the mappings between argument and parameter manually. */ for (int argumentIndex = 0; argumentIndex < argumentList.size(); argumentIndex++) { /* find $1, $2 ... and replace them with the correct argument. */ Argument argument = argumentList.get(argumentIndex); - if (!argument.isRequiredArgumentPlaceholder()) continue; + if (!isRequiredArgumentPlaceholder(argument)) continue; /* replace the required argument placeholder `$1` with the parameter in method whose index is 1*/ - int methodParameterIndex = argument.getMethodParameterIndex(); + int methodParameterIndex = parseMethodParameterIndexFromArgumentName(argument); Parameter parameter = method.getParameters()[methodParameterIndex]; Class type = unbox(parameter); boolean isOptional = parameter.getType().equals(Optional.class); argumentList.set(argumentIndex, Argument - .makeRequiredArgument(type, parameter.getName(), methodParameterIndex, isOptional, CommandRequirementDescriptor.of(methodRequirement)) + .makeRequiredArgument(type, parameter.getName(), isOptional, CommandRequirementDescriptor.of(methodRequirement)) + .markWithParameter(parameter) .withDocument(parameter.getAnnotation(Document.class)) ); } @@ -172,27 +189,23 @@ private static Class unbox(Parameter parameter) { Class type = unbox(parameter); // for a command source argument, we don't care the index argumentList.addFirst(Argument - .makeRequiredArgument(type, parameter.getName(), parameterIndex, false, CommandRequirementDescriptor.of(methodRequirement)).markAsCommandSource() + .makeRequiredArgument(type, parameter.getName(), false, CommandRequirementDescriptor.of(methodRequirement)) + .markWithParameter(parameter) .withDocument(parameter.getAnnotation(Document.class)) ); } } else { /* generate the mappings between argument and parameter automatically. */ Parameter[] parameters = method.getParameters(); - for (int parameterIndex = 0; parameterIndex < parameters.length; parameterIndex++) { + for (Parameter parameter : parameters) { /* append the argument to the tail*/ - Parameter parameter = parameters[parameterIndex]; Class type = unbox(parameter); boolean isOptional = parameter.getType().equals(Optional.class); Argument argument = Argument - .makeRequiredArgument(type, parameter.getName(), parameterIndex, isOptional, CommandRequirementDescriptor.of(methodRequirement)) + .makeRequiredArgument(type, parameter.getName(), isOptional, CommandRequirementDescriptor.of(methodRequirement)) + .markWithParameter(parameter) .withDocument(parameter.getAnnotation(Document.class)); argumentList.add(argument); - - /* mark as command source */ - if (parameter.isAnnotationPresent(CommandSource.class)) { - argument.markAsCommandSource(); - } } } diff --git a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java index 93c44361..8b2493ad 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java @@ -18,7 +18,6 @@ import io.github.sakurawald.core.command.exception.AbortCommandExecutionException; import io.github.sakurawald.core.command.processor.CommandAnnotationProcessor; import io.github.sakurawald.core.manager.impl.module.ModuleManager; -import lombok.Getter; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; @@ -38,10 +37,10 @@ import java.util.function.Predicate; import java.util.stream.Collectors; -@Getter public class CommandDescriptor { public final Method method; + public final List arguments; // it's null if get before register() @@ -111,10 +110,10 @@ private static LiteralArgumentBuilder makeRootArgumentBuild return (LiteralArgumentBuilder) root; } - private static String buildCommandNodePath(CommandNode node) { + private static String getCommandNodePath(CommandNode node) { StringBuilder sb = new StringBuilder(); sb.append(node.getName()); - node.getChildren().forEach(child -> sb.append(".").append(buildCommandNodePath(child))); + node.getChildren().forEach(child -> sb.append(".").append(getCommandNodePath(child))); return sb.toString(); } @@ -245,9 +244,9 @@ protected static void reportException(ServerCommandSource source, Method method, source.sendMessage(report); } - public String buildCommandNodePath() { + public String getCommandNodePath() { assert this.registerReturnValue != null; - return buildCommandNodePath(this.registerReturnValue.build()); + return getCommandNodePath(this.registerReturnValue.build()); } public void unregister() { @@ -268,13 +267,18 @@ public void unregister() { CommandAnnotationProcessor.descriptors.remove(this); } + protected List collectArgumentsToMakeCommandFunctionArgs() { + return this.arguments + .stream() + /* filter out the literal command node and root command node. */ + .filter(Argument::isRequiredArgument) + .toList(); + } + protected List makeCommandFunctionArgs(CommandContext ctx) { List args = new ArrayList<>(); - for (Argument argument : this.arguments) { - /* the literal argument doesn't receive a value. */ - if (argument.isLiteralArgument()) continue; - + for (Argument argument : this.collectArgumentsToMakeCommandFunctionArgs()) { /* inject the value into a required argument. */ try { Object arg = BaseArgumentTypeAdapter @@ -348,7 +352,6 @@ public LiteralArgumentBuilder register() { return root; } - @SuppressWarnings("UnusedReturnValue") private LiteralArgumentBuilder registerNonOptionalArguments() { /* make root builder */ @@ -384,19 +387,20 @@ public String toString() { return "/" + this.arguments.stream().map(Argument::toString).collect(Collectors.joining(" ")); } - public String computeCommandSyntax() { - StringBuilder sb = new StringBuilder() + public String getCommandSyntax() { + StringBuilder syntax = new StringBuilder() .append("/"); - this.getArguments().stream() + this.arguments.stream() .filter(it -> !it.isCommandSource()) - .forEach(it -> sb.append(it.toInGameString()).append(" ")); + .forEach(it -> syntax.append(it.toHumanReadableString()).append(" ")); - return sb.toString(); + return syntax.toString(); } - public int computeLevelPermission() { + public int getDefaultLevelPermission() { int minRequiredLevel = CommandRequirementDescriptor.getDefaultLevel(); + for (Argument argument : this.arguments) { if (argument.getRequirement() == null) continue; @@ -405,7 +409,7 @@ public int computeLevelPermission() { return minRequiredLevel; } - public String computeStringPermission() { + public String getDefaultStringPermission() { String requiredString = CommandRequirementDescriptor.getDefaultString(); for (Argument argument : this.arguments) { if (argument.getRequirement() == null) continue; @@ -424,6 +428,7 @@ public boolean canBeExecutedByConsole() { for (Argument argument : this.arguments) { if (!argument.isCommandSource()) continue; + assert argument.getType() != null; return argument.getType().equals(CommandContext.class) || argument.getType().equals(ServerCommandSource.class); } diff --git a/src/main/java/io/github/sakurawald/core/command/structure/CommandRequirementDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/CommandRequirementDescriptor.java index 4863111d..cb44a9df 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/CommandRequirementDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/CommandRequirementDescriptor.java @@ -2,19 +2,28 @@ import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.config.Configs; -import lombok.Data; +import lombok.Getter; import org.jetbrains.annotations.Nullable; -@Data +@SuppressWarnings("ClassCanBeRecord") +@Getter public class CommandRequirementDescriptor { final int level; final @Nullable String string; + public CommandRequirementDescriptor(int level, @Nullable String string) { + this.level = level; + + if (string != null && string.isBlank()) { + this.string = null; + } else this.string = string; + } + /* - 1. This function will not work for BundleCommandDescriptor, since the gson will create the java object via the reflection. - 2. The command `/command-callback` is registered directly via the brigadier system. - */ + 1. This function will not work for BundleCommandDescriptor, since the gson will create the java object via the reflection. + 2. The command `/command-callback` is registered directly via the brigadier system. + */ public static @Nullable CommandRequirementDescriptor of(@Nullable CommandRequirement annotation) { /* override the default requirement */ if (Configs.configHandler.model().core.permission.all_commands_require_level_4_permission_to_use_by_default) { @@ -25,6 +34,7 @@ public class CommandRequirementDescriptor { if (annotation == null) { return null; } + return new CommandRequirementDescriptor(annotation.level(), annotation.string()); } diff --git a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java index 6245ea32..b7edb91c 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java @@ -3,14 +3,12 @@ import com.mojang.brigadier.Command; import io.github.sakurawald.core.auxiliary.LogUtil; import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; -import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.structure.Argument; import io.github.sakurawald.core.command.argument.wrapper.impl.PlayerCollection; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -19,23 +17,50 @@ public class RetargetCommandDescriptor extends CommandDescriptor { private static final int COMMAND_TARGET_DUMMY_PARAMETER_INDEX = 1024; - private final int commandTargetAnnotationIndex; + private final int commandTargetArgumentIndex; - private RetargetCommandDescriptor(Method method, List arguments, int commandTargetAnnotationIndex) { + private RetargetCommandDescriptor(Method method, List arguments, int commandTargetArgumentIndex) { super(method, arguments); - this.commandTargetAnnotationIndex = commandTargetAnnotationIndex; + this.commandTargetArgumentIndex = commandTargetArgumentIndex; } - private static List transformWithOthersArguments(List arguments, int commandTargetAnnotationIndex) { + private static Optional findCommandTargetArgumentIndex(CommandDescriptor descriptor) { + for (int i = 0; i < descriptor.arguments.size(); i++) { + Argument argument = descriptor.arguments.get(i); + if (argument.isCommandTarget()) { + return Optional.of(i); + } + } + + return Optional.empty(); + } + + public static Optional make(CommandDescriptor commandDescriptor) { + /* filter: the method that contains @CommandTarget */ + Optional commandTargetArgumentIndexOpt = findCommandTargetArgumentIndex(commandDescriptor); + if (commandTargetArgumentIndexOpt.isEmpty()) { + return Optional.empty(); + } + int commandTargetArgumentIndex = commandTargetArgumentIndexOpt.get(); + + /* make retarget command descriptor */ + List transformedArgs = transformWithOthersArguments(commandDescriptor.arguments); + + RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(commandDescriptor.method, transformedArgs, commandTargetArgumentIndex); + return Optional.of(retargetCommandDescriptor); + } + + + private static List transformWithOthersArguments(List arguments) { List ret = new ArrayList<>(arguments .stream() .filter(it -> /* remove the argument that is annotated with @CommandTarget and is not annotated with @CommandSource, so that this argument will not be registered in the command tree. + Consider `/fly{4} others{4} (){4} (ST){4}` */ - it.isCommandSource() || - it.getMethodParameterIndex() != commandTargetAnnotationIndex + it.isCommandSource() || !it.isCommandTarget() ) .toList()); @@ -49,7 +74,7 @@ private static List transformWithOthersArguments(List argume CommandRequirementDescriptor requirement = new CommandRequirementDescriptor(4, null); ret.add(argumentIndex, Argument.makeLiteralArgument("others", requirement)); - ret.add(argumentIndex + 1, Argument.makeRequiredArgument(PlayerCollection.class, "others", COMMAND_TARGET_DUMMY_PARAMETER_INDEX, false, requirement)); + ret.add(argumentIndex + 1, Argument.makeRequiredArgument(PlayerCollection.class, "others", false, requirement)); break; } @@ -58,23 +83,6 @@ private static List transformWithOthersArguments(List argume return ret; } - private static Optional findCommandTargetAnnotationIndex(Method method) { - Parameter[] parameters = method.getParameters(); - for (int i = 0; i < parameters.length; i++) { - Parameter parameter = parameters[i]; - if (parameter.isAnnotationPresent(CommandTarget.class)) { - // verify - if (!parameter.getType().equals(ServerPlayerEntity.class)) { - throw new IllegalArgumentException("the annotation @CommandTarget can only be used in a parameter whose type is ServerPlayerEntity: class = %s, method = %s".formatted(method.getDeclaringClass().getSimpleName(), method.getName())); - } - - return Optional.of(i); - } - } - - return Optional.empty(); - } - @Override protected Command makeCommandFunctionClosure() { return (ctx) -> { @@ -91,11 +99,10 @@ protected Command makeCommandFunctionClosure() { /* apply the command execution for each target. */ PlayerCollection targets = (PlayerCollection) args.getFirst(); - LogUtil.debug("unbox the first argument and get the targets: {}", targets.getValue().stream().map(it -> it.getGameProfile().getName()).toList()); + LogUtil.debug("get the targets argument (the first argument in args): {}", targets.getValue().stream().map(it -> it.getGameProfile().getName()).toList()); int finalValue = CommandHelper.Return.SUCCESS; for (ServerPlayerEntity target : targets.getValue()) { - List unboxedArgs = args.subList(1, args.size()); /* if the @CommandSource and @CommandTarget are both annotated in the same parameter: @@ -103,11 +110,11 @@ protected Command makeCommandFunctionClosure() { 2. After that, the command source passed to the command method will be overridden by the @CommandTarget. 3. Any exceptions thrown during the execution of the command method, will be reported to the `initialing command source`. */ - if (this.commandTargetAnnotationIndex < unboxedArgs.size()) { - unboxedArgs.set(this.commandTargetAnnotationIndex, target); + if (this.commandTargetArgumentIndex < unboxedArgs.size()) { + unboxedArgs.set(this.commandTargetArgumentIndex, target); } else { // if the commandTargetAnnotationIndex < unboxedArgs, then it means the argument annotated with @CommandTarget is filtered. - unboxedArgs.add(this.commandTargetAnnotationIndex, target); + unboxedArgs.add(this.commandTargetArgumentIndex, target); } LogUtil.debug("invoke command method {} in class {}: target = {}, args = {}" @@ -136,21 +143,4 @@ protected Command makeCommandFunctionClosure() { return finalValue; }; } - - public static Optional make(CommandDescriptor commandDescriptor) { - /* filter: the method that contains @CommandTarget */ - Optional commandTargetAnnotationIndexOpt = findCommandTargetAnnotationIndex(commandDescriptor.method); - if (commandTargetAnnotationIndexOpt.isEmpty()) { - return Optional.empty(); - } - int commandTargetAnnotationIndex = commandTargetAnnotationIndexOpt.get(); - - /* make retarget command descriptor */ - Method delegateMethod = commandDescriptor.getMethod(); - List transformedArgs = transformWithOthersArguments(commandDescriptor.getArguments(), commandTargetAnnotationIndex); - - RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(delegateMethod, transformedArgs, commandTargetAnnotationIndex); - return Optional.of(retargetCommandDescriptor); - } - } diff --git a/src/main/java/io/github/sakurawald/core/gui/CommandDescriptorGui.java b/src/main/java/io/github/sakurawald/core/gui/CommandDescriptorGui.java index 85f49d09..4530b13e 100644 --- a/src/main/java/io/github/sakurawald/core/gui/CommandDescriptorGui.java +++ b/src/main/java/io/github/sakurawald/core/gui/CommandDescriptorGui.java @@ -49,13 +49,13 @@ protected GuiElementInterface toGuiElement(CommandDescriptor entity) { lore.addAll(List.of( TextHelper.getTextByKey(getPlayer(), "command.source.can_be_executed_by_console", entity.canBeExecutedByConsole()) , TextHelper.getTextByKey(getPlayer(), "command.descriptor.type", entity.getClass().getSimpleName()) - , TextHelper.getTextByKey(getPlayer(), "command.requirement.level_permission", entity.computeLevelPermission()) - , TextHelper.getTextByKey(getPlayer(), "command.requirement.string_permission", entity.computeStringPermission()) + , TextHelper.getTextByKey(getPlayer(), "command.requirement.level_permission", entity.getDefaultLevelPermission()) + , TextHelper.getTextByKey(getPlayer(), "command.requirement.string_permission", entity.getDefaultStringPermission()) )); lore.addAll(computeLore(entity)); return new GuiElementBuilder() - .setName(Text.literal(entity.computeCommandSyntax())) + .setName(Text.literal(entity.getCommandSyntax())) .setItem(Items.REPEATING_COMMAND_BLOCK) .setLore(lore) .build(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/CommandBundleInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/CommandBundleInitializer.java index 974cd555..4574379a 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/CommandBundleInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/CommandBundleInitializer.java @@ -64,7 +64,7 @@ private static int list(@CommandSource CommandContext ctx) if (ctx.getSource().isExecutedByPlayer()) { new CommandDescriptorGui(ctx.getSource().getPlayer(), commandDescriptorStream.toList(), 0).open(); } else { - commandDescriptorStream.forEach(it -> ctx.getSource().sendMessage(Text.literal(it.buildCommandNodePath()))); + commandDescriptorStream.forEach(it -> ctx.getSource().sendMessage(Text.literal(it.getCommandNodePath()))); } return CommandHelper.Return.SUCCESS; diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java index 4e98232c..b0b6210b 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java @@ -136,7 +136,7 @@ public static BundleCommandDescriptor make(BundleCommandNode entry) { String argumentType = matcher.group(REQUIRED_OPTIONAL_ARGUMENT_TYPE_GROUP_INDEX); String argumentName = matcher.group(REQUIRED_OPTIONAL_ARGUMENT_NAME_GROUP_INDEX); Class type = BaseArgumentTypeAdapter.toTypeClass(argumentType); - arguments.add(Argument.makeRequiredArgument(type, argumentName, argumentIndex, true, requirement)); + arguments.add(Argument.makeRequiredArgument(type, argumentName, true, requirement)); // put default value for optional argument String defaultValue = matcher.group(REQUIRED_OPTIONAL_ARGUMENT_DEFAULT_VALUE_GROUP_INDEX); @@ -149,7 +149,7 @@ public static BundleCommandDescriptor make(BundleCommandNode entry) { String argumentType = matcher.group(REQUIRED_NON_OPTIONAL_ARGUMENT_TYPE_GROUP_INDEX); String argumentName = matcher.group(REQUIRED_NON_OPTIONAL_ARGUMENT_NAME_GROUP_INDEX); Class type = BaseArgumentTypeAdapter.toTypeClass(argumentType); - arguments.add(Argument.makeRequiredArgument(type, argumentName, argumentIndex, false, requirement)); + arguments.add(Argument.makeRequiredArgument(type, argumentName, false, requirement)); } } @@ -169,15 +169,11 @@ protected List makeCommandFunctionArgs(CommandContext args = new ArrayList<>(); CommandContextAccessor ctxAccessor = (CommandContextAccessor) ctx; - for (Argument argument : this.arguments) { - /* filter the literal command node and root command node. */ - if (!(argument.isRequiredArgument())) continue; - + for (Argument argument : this.collectArgumentsToMakeCommandFunctionArgs()) { String argumentName = argument.getArgumentName(); /* collect the matched lexeme. */ String arg; - ParsedArgument parsedArgument = ctxAccessor.fuji$getArguments().get(argumentName); if (parsedArgument != null) { StringRange range = parsedArgument.getRange(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/fuji/FujiInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/fuji/FujiInitializer.java index 8d9a07b3..2f75b0e2 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/fuji/FujiInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/fuji/FujiInitializer.java @@ -118,7 +118,7 @@ private static int debug(@CommandSource ServerCommandSource source) { List descriptors = CommandAnnotationProcessor .descriptors .stream() - .sorted(Comparator.comparing(CommandDescriptor::buildCommandNodePath)) + .sorted(Comparator.comparing(CommandDescriptor::getCommandNodePath)) .toList(); new CommandDescriptorGui(player, descriptors, 0).open(); diff --git a/src/test/java/tests/ArgumentMakerTest.java b/src/test/java/tests/ArgumentMakerTest.java index 59d28617..3ca816be 100644 --- a/src/test/java/tests/ArgumentMakerTest.java +++ b/src/test/java/tests/ArgumentMakerTest.java @@ -17,7 +17,7 @@ public class ArgumentMakerTest { void test1() { BundleCommandDescriptor descriptor = BundleCommandDescriptor.make(new BundleCommandNode(null, "my-command [str str-arg-name]", null)); System.out.println(descriptor); - List args = descriptor.getArguments(); + List args = descriptor.arguments; Argument firstArg = args.getFirst(); assertTrue(firstArg.isLiteralArgument()); @@ -41,7 +41,7 @@ void test2() { BundleCommandDescriptor descriptor = BundleCommandDescriptor.make(new BundleCommandNode(null, "my-command first-literal [str str-arg-name] second-literal", null)); System.out.println(descriptor); - List args = descriptor.getArguments(); + List args = descriptor.arguments; Argument firstArg = args.getFirst(); assertTrue(firstArg.isLiteralArgument()); @@ -74,7 +74,7 @@ void test3() { BundleCommandDescriptor descriptor = BundleCommandDescriptor.make(new BundleCommandNode(null, "my-command [str str-arg-name hello world] first-literal", null)); System.out.println(descriptor); - List args = descriptor.getArguments(); + List args = descriptor.arguments; Argument firstArg = args.getFirst(); assertTrue(firstArg.isLiteralArgument()); From ba8df6b1b42efd723078e043c33c09d4a4316324 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 30 Oct 2024 10:14:44 +0000 Subject: [PATCH 06/16] i18n: new translations from crowdin --- crowdin/id_ID.json | 2 +- crowdin/zh_TW.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crowdin/id_ID.json b/crowdin/id_ID.json index e91e7a6e..4a88736c 100644 --- a/crowdin/id_ID.json +++ b/crowdin/id_ID.json @@ -271,7 +271,7 @@ "command_cooldown.not_found": "Cooldown %s tidak ditemukan.", "command_cooldown.already_exists": "Cooldown %s sudah ada.", "command_cooldown.deleted": "Cooldown %s dihapus.", - "command_cooldown.created": "The cooldown `%s` created.", + "command_cooldown.created": "Cooldown `%s` telah dibuat.", "echo.send_custom.custom_text.not_found": "Teks khusus %s tidak ditemukan.", "echo.send_custom.custom_text.invalid_page": "Halaman tidak valid.", "echo.send_custom.custom_text.paginator.first_page": "-----<< Sebelumnya %d/%d click:run_command:'%s'Berikutnya >>----", diff --git a/crowdin/zh_TW.json b/crowdin/zh_TW.json index 2a83ec0b..2ff75017 100644 --- a/crowdin/zh_TW.json +++ b/crowdin/zh_TW.json @@ -271,7 +271,7 @@ "command_cooldown.not_found": "找不到冷卻時間 %s。", "command_cooldown.already_exists": "冷卻時間 %s 已存在。", "command_cooldown.deleted": "已刪除冷卻時間 %s。", - "command_cooldown.created": "The cooldown `%s` created.", + "command_cooldown.created": "已建立冷卻時間 %s。", "echo.send_custom.custom_text.not_found": "找不到自訂文字 %s。", "echo.send_custom.custom_text.invalid_page": "無效的頁面。", "echo.send_custom.custom_text.paginator.first_page": "-----<< 上一頁 %d/%d 下一頁 >>----", From ee53806978a2c4981879a093b1ecdb5be16d562d Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:14:55 +0800 Subject: [PATCH 07/16] refactor: remove the parameter index field in CommandDescriptor --- .../processor/CommandAnnotationProcessor.java | 6 +++--- .../structure/RetargetCommandDescriptor.java | 15 ++++++++------- .../initializer/tester/TesterInitializer.java | 5 ++++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java index ad555f50..b22a8185 100644 --- a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java +++ b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java @@ -94,11 +94,11 @@ private static void processMethod(Class clazz, Method method) { /* make command descriptor */ CommandDescriptor descriptor = makeCommandDescriptor(clazz, method); - - /* register the command descriptor */ descriptor.register(); - RetargetCommandDescriptor.make(descriptor) + /* make retarget command descriptor */ + RetargetCommandDescriptor + .make(descriptor) .ifPresent(CommandDescriptor::register); } diff --git a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java index b7edb91c..215c854e 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java @@ -70,14 +70,15 @@ private static List transformWithOthersArguments(List argume /* ensure the `others` args are the `first required argument`, so that the `makeCommandFunctionArgs()` can extract the targets in the first arg */ if (argument.isRequiredArgument() || argumentIndex == ret.size() - 1) { - /* all retarget commands require level 4 permission to use */ + /* all retarget commands require level 4 permission to use. + * There is a bug about the tab completion for `/warp tp others`. + */ CommandRequirementDescriptor requirement = new CommandRequirementDescriptor(4, null); ret.add(argumentIndex, Argument.makeLiteralArgument("others", requirement)); ret.add(argumentIndex + 1, Argument.makeRequiredArgument(PlayerCollection.class, "others", false, requirement)); break; } - } return ret; @@ -103,20 +104,20 @@ protected Command makeCommandFunctionClosure() { int finalValue = CommandHelper.Return.SUCCESS; for (ServerPlayerEntity target : targets.getValue()) { - List unboxedArgs = args.subList(1, args.size()); /* if the @CommandSource and @CommandTarget are both annotated in the same parameter: 1. The @CommandSource will still be used to verify the type of `initialing command source`. 2. After that, the command source passed to the command method will be overridden by the @CommandTarget. 3. Any exceptions thrown during the execution of the command method, will be reported to the `initialing command source`. */ - if (this.commandTargetArgumentIndex < unboxedArgs.size()) { - unboxedArgs.set(this.commandTargetArgumentIndex, target); + if (this.commandTargetArgumentIndex < args.size()) { + args.set(this.commandTargetArgumentIndex, target); } else { - // if the commandTargetAnnotationIndex < unboxedArgs, then it means the argument annotated with @CommandTarget is filtered. - unboxedArgs.add(this.commandTargetArgumentIndex, target); + // if the commandTargetAnnotationIndex < args, then it means the argument annotated with @CommandTarget is filtered. + args.add(this.commandTargetArgumentIndex, target); } + List unboxedArgs = args.subList(1, args.size()); LogUtil.debug("invoke command method {} in class {}: target = {}, args = {}" , this.method.getName() , this.method.getDeclaringClass().getSimpleName() diff --git a/src/main/java/io/github/sakurawald/module/initializer/tester/TesterInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/tester/TesterInitializer.java index 936d6441..81d10a0c 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/tester/TesterInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/tester/TesterInitializer.java @@ -2,6 +2,7 @@ import com.mojang.brigadier.context.CommandContext; import io.github.sakurawald.core.auxiliary.LogUtil; +import io.github.sakurawald.core.auxiliary.minecraft.ServerHelper; import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; @@ -15,6 +16,7 @@ import net.minecraft.util.Formatting; import java.util.HashMap; +import java.util.List; import java.util.Map; @CommandNode("tester") @@ -27,8 +29,9 @@ public class TesterInitializer extends ModuleInitializer { @CommandNode("run") private static int $run(@CommandSource ServerPlayerEntity player) { - testTextReplacement(player); + com.mojang.brigadier.tree.CommandNode node = ServerHelper.getCommandDispatcher().findNode(List.of("warp", "tp", "others")); + LogUtil.debug("requires = {}", node.getRequirement()); return 1; } From c13b8439413485c5793ede01240b546ce101dd0a Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:27:20 +0800 Subject: [PATCH 08/16] refactor: set default requirement to level 4 permission to use all functional commands --- .../module/initializer/functional/anvil/AnvilInitializer.java | 2 ++ .../functional/cartography/CartographyInitializer.java | 2 ++ .../functional/enchantment/EnchantmentInitializer.java | 2 ++ .../functional/enderchest/EnderChestInitializer.java | 2 ++ .../functional/grindstone/GrindStoneInitializer.java | 2 ++ .../module/initializer/functional/loom/LoomInitializer.java | 2 ++ .../initializer/functional/smithing/SmithInitializer.java | 2 ++ .../functional/stonecutter/StoneCutterInitializer.java | 2 ++ .../initializer/functional/workbench/WorkbenchInitializer.java | 2 ++ 9 files changed, 18 insertions(+) diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java index 19d79643..b93448ae 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/anvil/AnvilInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class AnvilInitializer extends ModuleInitializer { @CommandNode("anvil") + @CommandRequirement(level = 4) private static int $anvil(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new AnvilScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java index 4bb47de0..7ed24f16 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/cartography/CartographyInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -15,6 +16,7 @@ public class CartographyInitializer extends ModuleInitializer { @CommandNode("cartography") + @CommandRequirement(level = 4) private static int $cartography(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new CartographyTableScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java index 7940fcba..4ae78cd2 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/enchantment/EnchantmentInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.config.handler.abst.BaseConfigurationHandler; @@ -19,6 +20,7 @@ public class EnchantmentInitializer extends ModuleInitializer { public static final BaseConfigurationHandler config = new ObjectConfigurationHandler<>(BaseConfigurationHandler.CONFIG_JSON, EnchantmentConfigModel.class); @CommandNode("enchantment") + @CommandRequirement(level = 4) private static int $enchantment(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new MyEnchantmentScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { }, Text.translatable("container.enchant"))); diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java index 5c971183..983be736 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/enderchest/EnderChestInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class EnderChestInitializer extends ModuleInitializer { @CommandNode("enderchest") + @CommandRequirement(level = 4) private static int $enderchest(@CommandSource @CommandTarget ServerPlayerEntity player) { EnderChestInventory enderChestInventory = player.getEnderChestInventory(); player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> GenericContainerScreenHandler.createGeneric9x3(i, inventory, enderChestInventory), Text.translatable("container.enderchest"))); diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java index 68c358f8..baf3dfe3 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/grindstone/GrindStoneInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class GrindStoneInitializer extends ModuleInitializer { @CommandNode("grindstone") + @CommandRequirement(level = 4) private static int $grindstone(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new GrindstoneScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java index 085c6474..0f24a6eb 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/loom/LoomInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class LoomInitializer extends ModuleInitializer { @CommandNode("loom") + @CommandRequirement(level = 4) private static int $loom(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new LoomScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java index ee0a69d4..2338e53b 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/smithing/SmithInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class SmithInitializer extends ModuleInitializer { @CommandNode("smithing") + @CommandRequirement(level = 4) private static int $smithing(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new SmithingScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java index 1ad856e2..a24141bf 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/stonecutter/StoneCutterInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class StoneCutterInitializer extends ModuleInitializer { @CommandNode("stonecutter") + @CommandRequirement(level = 4) private static int $stonecutter(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new StonecutterScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override diff --git a/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java index e6e2ffe5..b52f6b1e 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/functional/workbench/WorkbenchInitializer.java @@ -2,6 +2,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -16,6 +17,7 @@ public class WorkbenchInitializer extends ModuleInitializer { @CommandNode("workbench") + @CommandRequirement(level = 4) private static int $workbench(@CommandSource @CommandTarget ServerPlayerEntity player) { player.openHandledScreen(new SimpleNamedScreenHandlerFactory((i, inventory, p) -> new CraftingScreenHandler(i, inventory, ScreenHandlerContext.create(p.getWorld(), p.getBlockPos())) { @Override From 063ffcec79cd279239c979fa2fa48ee56d23e7d8 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:33:13 +0800 Subject: [PATCH 09/16] i18n: merge --- src/main/resources/io/github/sakurawald/lang/id_ID.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/io/github/sakurawald/lang/id_ID.json b/src/main/resources/io/github/sakurawald/lang/id_ID.json index e91e7a6e..4a88736c 100644 --- a/src/main/resources/io/github/sakurawald/lang/id_ID.json +++ b/src/main/resources/io/github/sakurawald/lang/id_ID.json @@ -271,7 +271,7 @@ "command_cooldown.not_found": "Cooldown %s tidak ditemukan.", "command_cooldown.already_exists": "Cooldown %s sudah ada.", "command_cooldown.deleted": "Cooldown %s dihapus.", - "command_cooldown.created": "The cooldown `%s` created.", + "command_cooldown.created": "Cooldown `%s` telah dibuat.", "echo.send_custom.custom_text.not_found": "Teks khusus %s tidak ditemukan.", "echo.send_custom.custom_text.invalid_page": "Halaman tidak valid.", "echo.send_custom.custom_text.paginator.first_page": "-----<< Sebelumnya %d/%d click:run_command:'%s'Berikutnya >>----", From 3a3e5d4347c809da52904a408ab9ec86c0641173 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:33:28 +0800 Subject: [PATCH 10/16] refactor: set default permission level --- .../command_toolbox/extinguish/ExtinguishInitializer.java | 2 ++ .../initializer/command_toolbox/near/NearInitializer.java | 2 ++ .../initializer/command_toolbox/ping/PingInitializer.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java index c1cc4e67..59826800 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/extinguish/ExtinguishInitializer.java @@ -3,6 +3,7 @@ import io.github.sakurawald.core.annotation.Document; import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.module.initializer.ModuleInitializer; @@ -13,6 +14,7 @@ public class ExtinguishInitializer extends ModuleInitializer { @CommandNode("extinguish") + @CommandRequirement(level = 4) @Document("Set fire ticks to 0.") private static int $extinguish(@CommandSource @CommandTarget ServerPlayerEntity player) { player.setFireTicks(0); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/near/NearInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/near/NearInitializer.java index 66542454..16b650c7 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/near/NearInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/near/NearInitializer.java @@ -5,6 +5,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.ServerHelper; import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.MinecraftServer; @@ -21,6 +22,7 @@ private static int distance(ServerPlayerEntity a, ServerPlayerEntity b) { } @CommandNode("near") + @CommandRequirement(level = 4) @Document("List nearby players.") private static int near(@CommandSource ServerPlayerEntity player, Optional distance) { MinecraftServer server = ServerHelper.getServer(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/ping/PingInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/ping/PingInitializer.java index 40a5f45d..30946ad0 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/ping/PingInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/ping/PingInitializer.java @@ -4,6 +4,7 @@ import io.github.sakurawald.core.auxiliary.minecraft.CommandHelper; import io.github.sakurawald.core.auxiliary.minecraft.TextHelper; import io.github.sakurawald.core.command.annotation.CommandNode; +import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; import io.github.sakurawald.module.initializer.ModuleInitializer; import net.minecraft.server.command.ServerCommandSource; @@ -13,6 +14,7 @@ public class PingInitializer extends ModuleInitializer { @CommandNode("ping") + @CommandRequirement(level = 4) @Document("Query the ping of a player.") private static int $ping(@CommandSource ServerCommandSource source, ServerPlayerEntity target) { String name = target.getGameProfile().getName(); From df681d90296882fa732475e0053a276964e5f1b2 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:36:45 +0800 Subject: [PATCH 11/16] i18n: merge --- src/main/resources/io/github/sakurawald/lang/zh_TW.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/io/github/sakurawald/lang/zh_TW.json b/src/main/resources/io/github/sakurawald/lang/zh_TW.json index 2a83ec0b..2ff75017 100644 --- a/src/main/resources/io/github/sakurawald/lang/zh_TW.json +++ b/src/main/resources/io/github/sakurawald/lang/zh_TW.json @@ -271,7 +271,7 @@ "command_cooldown.not_found": "找不到冷卻時間 %s。", "command_cooldown.already_exists": "冷卻時間 %s 已存在。", "command_cooldown.deleted": "已刪除冷卻時間 %s。", - "command_cooldown.created": "The cooldown `%s` created.", + "command_cooldown.created": "已建立冷卻時間 %s。", "echo.send_custom.custom_text.not_found": "找不到自訂文字 %s。", "echo.send_custom.custom_text.invalid_page": "無效的頁面。", "echo.send_custom.custom_text.paginator.first_page": "-----<< 上一頁 %d/%d 下一頁 >>----", From 0d0f1754ba2174f2e7f91ac4d8aac67d4a114f69 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:37:06 +0800 Subject: [PATCH 12/16] build: write changelog --- CHANGELOG.md | 18 ++++++++++++------ gradle.properties | 2 +- .../structure/RetargetCommandDescriptor.java | 2 -- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6148a234..0e86a2cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ -> The version number of fuji follows `semver` now: https://semver.org/ - +> The version number of fuji follows `semver` now: https://semver.org/ -- feature: add `on_warped` event for warps. (command_toolbox.warp module) -- fix: possible to trigger `Not a JSON Object: null` when a new fake-player is spawned via `carpet` mod. (placeholder module) -- fix: can't display a specific type of block entity properly, e.g. beds, banners etc. (chunks module) -- refactor: cleanup unused functions in core, rename and simplify symbols in core. \ No newline at end of file +> This version includes the following **breaking changes** if you are using them: +> - feature: add `others` literal arguments to most commands that only targeted at command source player in the past, + now allows to use `others` argument to apply the command to a collection of players. This influence the following + commands (**If you are using `command_permission module` with `apply-sponge-implicit-wildcard=false` + in `luckperms.conf`, then everything is fine. If the option is true, then be careful that the `wildcard permission` + may allow players to use the following commands with `others` option.**): + > +> - most of the commands in `command_toolbox` +> - /afk, /back, /chat style, /pvp, /rtp +> - make the default required level permission to 4: /heal, /ping, /extinguish, /near (command_toolbox.* module) +> - make the default required level permission to 4: all functional commands. (functional module) diff --git a/gradle.properties b/gradle.properties index 309b6a52..85590b9b 100755 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.parallel=true # project maven_group=io.github.sakurawald mod_id=fuji -mod_version=4.3.0 +mod_version=5.0.0 # loader minecraft_version=1.21.2 diff --git a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java index 215c854e..51da691e 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java @@ -15,8 +15,6 @@ public class RetargetCommandDescriptor extends CommandDescriptor { - private static final int COMMAND_TARGET_DUMMY_PARAMETER_INDEX = 1024; - private final int commandTargetArgumentIndex; private RetargetCommandDescriptor(Method method, List arguments, int commandTargetArgumentIndex) { From 6c0879ee69ab4106e592ba67864b2a20be4652f5 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:44:38 +0800 Subject: [PATCH 13/16] refactor: add @CommandTarget for /tppos --- .../command_toolbox/tppos/TpposInitializer.java | 9 ++------- .../module/initializer/nametag/NametagInitializer.java | 1 + 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/tppos/TpposInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/tppos/TpposInitializer.java index 23f08cef..c51e1f5b 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/tppos/TpposInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_toolbox/tppos/TpposInitializer.java @@ -7,6 +7,7 @@ import io.github.sakurawald.core.command.annotation.CommandNode; import io.github.sakurawald.core.command.annotation.CommandRequirement; import io.github.sakurawald.core.command.annotation.CommandSource; +import io.github.sakurawald.core.command.annotation.CommandTarget; import io.github.sakurawald.core.command.argument.wrapper.impl.Dimension; import io.github.sakurawald.core.command.argument.wrapper.impl.OfflinePlayerName; import io.github.sakurawald.core.service.random_teleport.RandomTeleporter; @@ -23,8 +24,7 @@ public class TpposInitializer extends ModuleInitializer { @CommandNode("tppos") @CommandRequirement(level = 4) @Document("The unified teleport command.") - private static int tppos(@CommandSource ServerPlayerEntity player - , @Document("the target player") Optional targetPlayer + private static int tppos(@CommandSource @CommandTarget ServerPlayerEntity player , @Document("the target dimension") Optional dimension , @Document("the target x for fixed-tp") Optional x , @Document("the target y for fixed-tp") Optional y @@ -40,11 +40,6 @@ private static int tppos(@CommandSource ServerPlayerEntity player , @Document("max y for rtp") Optional maxY , @Document("max try times for rtp") Optional maxTryTimes ) { - // specify another player - if (targetPlayer.isPresent()) { - player = targetPlayer.get(); - } - /* specify the dimension */ ServerWorld world = dimension.isPresent() ? dimension.get().getValue() : player.getServerWorld(); diff --git a/src/main/java/io/github/sakurawald/module/initializer/nametag/NametagInitializer.java b/src/main/java/io/github/sakurawald/module/initializer/nametag/NametagInitializer.java index 9874479d..c7be1be4 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/nametag/NametagInitializer.java +++ b/src/main/java/io/github/sakurawald/module/initializer/nametag/NametagInitializer.java @@ -56,6 +56,7 @@ public void tick() { /* discard nametag if the vehicle is sneaking */ if (this.getVehicle().isSneaking()) { + LogUtil.debug("discard nametag entity {}: its vehicle is sneaking", this); this.discardNametag(); } From 18a797dcadea9fd55c25be5199f3300813c70d8f Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 19:45:29 +0800 Subject: [PATCH 14/16] build: write changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e86a2cb..8985f8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ commands (**If you are using `command_permission module` with `apply-sponge-implicit-wildcard=false` in `luckperms.conf`, then everything is fine. If the option is true, then be careful that the `wildcard permission` may allow players to use the following commands with `others` option.**): - > +> - all functional commands. > - most of the commands in `command_toolbox` > - /afk, /back, /chat style, /pvp, /rtp +> - The command option `/tppos --targetPlayer ...` is replaced by `/tppos others ...`. (command_toolbox.tppos module) > - make the default required level permission to 4: /heal, /ping, /extinguish, /near (command_toolbox.* module) > - make the default required level permission to 4: all functional commands. (functional module) From f1ea2d98baf2d5b86174df2e9b923786064f4a36 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 20:30:11 +0800 Subject: [PATCH 15/16] refactor: rename makeCommandFunctionArgs() to makeObjectsByArguments() --- .../processor/CommandAnnotationProcessor.java | 9 ++-- .../command/structure/CommandDescriptor.java | 8 ++-- .../structure/RetargetCommandDescriptor.java | 42 ++++++++++--------- .../structure/BundleCommandDescriptor.java | 6 +-- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java index b22a8185..9956a50e 100644 --- a/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java +++ b/src/main/java/io/github/sakurawald/core/command/processor/CommandAnnotationProcessor.java @@ -176,10 +176,11 @@ private static int parseMethodParameterIndexFromArgumentName(Argument argument) Parameter parameter = method.getParameters()[methodParameterIndex]; Class type = unbox(parameter); boolean isOptional = parameter.getType().equals(Optional.class); - argumentList.set(argumentIndex, Argument - .makeRequiredArgument(type, parameter.getName(), isOptional, CommandRequirementDescriptor.of(methodRequirement)) - .markWithParameter(parameter) - .withDocument(parameter.getAnnotation(Document.class)) + argumentList.set(argumentIndex, + Argument + .makeRequiredArgument(type, parameter.getName(), isOptional, CommandRequirementDescriptor.of(methodRequirement)) + .markWithParameter(parameter) + .withDocument(parameter.getAnnotation(Document.class)) ); } /* generate the command source argument for lazy programmers. */ diff --git a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java index 8b2493ad..9d1d6577 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/CommandDescriptor.java @@ -267,7 +267,7 @@ public void unregister() { CommandAnnotationProcessor.descriptors.remove(this); } - protected List collectArgumentsToMakeCommandFunctionArgs() { + protected List collectArgumentsToMakeObjects() { return this.arguments .stream() /* filter out the literal command node and root command node. */ @@ -275,10 +275,10 @@ protected List collectArgumentsToMakeCommandFunctionArgs() { .toList(); } - protected List makeCommandFunctionArgs(CommandContext ctx) { + protected List makeObjectsByArguments(CommandContext ctx) { List args = new ArrayList<>(); - for (Argument argument : this.collectArgumentsToMakeCommandFunctionArgs()) { + for (Argument argument : this.collectArgumentsToMakeObjects()) { /* inject the value into a required argument. */ try { Object arg = BaseArgumentTypeAdapter @@ -322,7 +322,7 @@ protected Command makeCommandFunctionClosure() { } /* invoke the command function */ - List args = makeCommandFunctionArgs(ctx); + List args = makeObjectsByArguments(ctx); int value; try { diff --git a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java index 51da691e..62c2482c 100644 --- a/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/core/command/structure/RetargetCommandDescriptor.java @@ -15,16 +15,18 @@ public class RetargetCommandDescriptor extends CommandDescriptor { - private final int commandTargetArgumentIndex; + private final int parameterIndexOfCommandTarget; - private RetargetCommandDescriptor(Method method, List arguments, int commandTargetArgumentIndex) { + private RetargetCommandDescriptor(Method method, List arguments, int parameterIndexOfCommandTarget) { super(method, arguments); - this.commandTargetArgumentIndex = commandTargetArgumentIndex; + this.parameterIndexOfCommandTarget = parameterIndexOfCommandTarget; } - private static Optional findCommandTargetArgumentIndex(CommandDescriptor descriptor) { - for (int i = 0; i < descriptor.arguments.size(); i++) { - Argument argument = descriptor.arguments.get(i); + private static Optional computeParameterIndexOfCommandTarget(CommandDescriptor descriptor) { + List args = descriptor.collectArgumentsToMakeObjects(); + + for (int i = 0; i < args.size(); i++) { + Argument argument = args.get(i); if (argument.isCommandTarget()) { return Optional.of(i); } @@ -35,16 +37,16 @@ private static Optional findCommandTargetArgumentIndex(CommandDescripto public static Optional make(CommandDescriptor commandDescriptor) { /* filter: the method that contains @CommandTarget */ - Optional commandTargetArgumentIndexOpt = findCommandTargetArgumentIndex(commandDescriptor); - if (commandTargetArgumentIndexOpt.isEmpty()) { + Optional indexOpt = computeParameterIndexOfCommandTarget(commandDescriptor); + if (indexOpt.isEmpty()) { return Optional.empty(); } - int commandTargetArgumentIndex = commandTargetArgumentIndexOpt.get(); + int index = indexOpt.get(); /* make retarget command descriptor */ List transformedArgs = transformWithOthersArguments(commandDescriptor.arguments); - RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(commandDescriptor.method, transformedArgs, commandTargetArgumentIndex); + RetargetCommandDescriptor retargetCommandDescriptor = new RetargetCommandDescriptor(commandDescriptor.method, transformedArgs, index); return Optional.of(retargetCommandDescriptor); } @@ -94,10 +96,10 @@ protected Command makeCommandFunctionClosure() { LogUtil.debug("execute retarget command: initialing command source = {}", ctx.getSource().getName()); /* invoke the command function */ - List args = makeCommandFunctionArgs(ctx); + List objs = makeObjectsByArguments(ctx); /* apply the command execution for each target. */ - PlayerCollection targets = (PlayerCollection) args.getFirst(); + PlayerCollection targets = (PlayerCollection) objs.getFirst(); LogUtil.debug("get the targets argument (the first argument in args): {}", targets.getValue().stream().map(it -> it.getGameProfile().getName()).toList()); int finalValue = CommandHelper.Return.SUCCESS; @@ -108,27 +110,27 @@ protected Command makeCommandFunctionClosure() { 2. After that, the command source passed to the command method will be overridden by the @CommandTarget. 3. Any exceptions thrown during the execution of the command method, will be reported to the `initialing command source`. */ - if (this.commandTargetArgumentIndex < args.size()) { - args.set(this.commandTargetArgumentIndex, target); + List args = objs.subList(1, objs.size()); + if (this.parameterIndexOfCommandTarget < args.size()) { + args.set(this.parameterIndexOfCommandTarget, target); } else { - // if the commandTargetAnnotationIndex < args, then it means the argument annotated with @CommandTarget is filtered. - args.add(this.commandTargetArgumentIndex, target); + // if the index < unboxedArgs.size(), then it means the argument annotated with @CommandTarget is removed. + args.add(this.parameterIndexOfCommandTarget, target); } - List unboxedArgs = args.subList(1, args.size()); LogUtil.debug("invoke command method {} in class {}: target = {}, args = {}" , this.method.getName() , this.method.getDeclaringClass().getSimpleName() , target.getGameProfile().getName() - , unboxedArgs); + , args); try { // if one of the execution if failed, then it's considered the whole return value is failed. - int singleValue = (int) this.method.invoke(null, unboxedArgs.toArray()); + int singleValue = (int) this.method.invoke(null, args.toArray()); LogUtil.debug("the return value of command method is {}: target = {}, args = {}" , singleValue , target.getGameProfile().getName() - , unboxedArgs); + , args); if (singleValue != CommandHelper.Return.SUCCESS) { finalValue = CommandHelper.Return.FAIL; diff --git a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java index b0b6210b..7302e2ec 100644 --- a/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java +++ b/src/main/java/io/github/sakurawald/module/initializer/command_bundle/structure/BundleCommandDescriptor.java @@ -165,11 +165,11 @@ private static boolean matchLiteralArgument(Matcher matcher) { } @Override - protected List makeCommandFunctionArgs(CommandContext ctx) { + protected List makeObjectsByArguments(CommandContext ctx) { List args = new ArrayList<>(); CommandContextAccessor ctxAccessor = (CommandContextAccessor) ctx; - for (Argument argument : this.collectArgumentsToMakeCommandFunctionArgs()) { + for (Argument argument : this.collectArgumentsToMakeObjects()) { String argumentName = argument.getArgumentName(); /* collect the matched lexeme. */ @@ -197,7 +197,7 @@ protected Command makeCommandFunctionClosure() { /* invoke the command function */ BundleCommandDescriptor descriptor = this; - List args = makeCommandFunctionArgs(ctx); + List args = makeObjectsByArguments(ctx); int value; try { From 82a2c2b587762c088b81f76ffb1bc1ce886c6564 Mon Sep 17 00:00:00 2001 From: sakurawald Date: Wed, 30 Oct 2024 20:33:29 +0800 Subject: [PATCH 16/16] docs: compile --- docs/release/fuji.pdf | Bin 460564 -> 461039 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/release/fuji.pdf b/docs/release/fuji.pdf index 7bc6cd00a640e24429aae7e4e49f6e13ae5d30bb..775de50d0e713b639f1dc51417227bd870aadae1 100644 GIT binary patch delta 47943 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 a@f}3XDR~DOg%bUx03SLXos6n1`hNfzH-Cu$ delta 47499 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