diff --git a/src/main/java/org/auioc/mcmod/arnicalib/server/command/AHServerCommands.java b/src/main/java/org/auioc/mcmod/arnicalib/server/command/AHServerCommands.java index 6a2985a9..419408e7 100644 --- a/src/main/java/org/auioc/mcmod/arnicalib/server/command/AHServerCommands.java +++ b/src/main/java/org/auioc/mcmod/arnicalib/server/command/AHServerCommands.java @@ -5,8 +5,8 @@ import org.auioc.mcmod.arnicalib.ArnicaLib; import org.auioc.mcmod.arnicalib.common.command.impl.VersionCommand; import org.auioc.mcmod.arnicalib.server.command.impl.RtpCommand; -import org.auioc.mcmod.arnicalib.utils.game.DynamicCommandHandler; import org.auioc.mcmod.arnicalib.utils.game.EnvironmentUtils; +import org.auioc.mcmod.arnicalib.utils.game.command.DynamicCommandHandler; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.tree.CommandNode; import net.minecraft.commands.CommandSourceStack; diff --git a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/CommandUtils.java b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/CommandUtils.java index 6d4fe9c9..bf330386 100644 --- a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/CommandUtils.java +++ b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/CommandUtils.java @@ -1,97 +1,54 @@ package org.auioc.mcmod.arnicalib.utils.game; -import static org.auioc.mcmod.arnicalib.ArnicaLib.i18n; -import static org.auioc.mcmod.arnicalib.utils.game.TextUtils.translatable; -import java.lang.reflect.Field; import java.util.List; import java.util.function.Predicate; -import java.util.stream.Collectors; -import org.auioc.mcmod.arnicalib.api.mixin.common.IMixinCommandSourceStack; -import com.mojang.brigadier.context.CommandContext; +import org.auioc.mcmod.arnicalib.utils.game.command.CommandExceptions; +import org.auioc.mcmod.arnicalib.utils.game.command.CommandNodeUtils; +import org.auioc.mcmod.arnicalib.utils.game.command.CommandSourceUtils; import com.mojang.brigadier.context.ParsedCommandNode; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.brigadier.tree.LiteralCommandNode; import net.minecraft.client.player.LocalPlayer; import net.minecraft.commands.CommandSource; import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +@Deprecated(since = "5.4.4", forRemoval = true) public interface CommandUtils { - SimpleCommandExceptionType INTERNAL_ERROR = new SimpleCommandExceptionType(translatable(i18n("command.failure.internal"))); - SimpleCommandExceptionType LOGGABLE_INTERNAL_ERROR = new SimpleCommandExceptionType(translatable(i18n("command.failure.internal.loggable"))); - SimpleCommandExceptionType NOT_SERVER_ERROR = new SimpleCommandExceptionType(translatable(i18n("command.failure.not_server"))); - SimpleCommandExceptionType NOT_DEDICATED_SERVER_ERROR = new SimpleCommandExceptionType(translatable(i18n("command.failure.not_dedicated_server"))); - SimpleCommandExceptionType GET_REAL_SOURCE_REFLECTION_ERROR = new SimpleCommandExceptionType(translatable(i18n("command.failure.get_real_source.reflection"))); - - Predicate IS_PLAYER = (source) -> source.getEntity() instanceof ServerPlayer; - Predicate PERMISSION_LEVEL_0 = (source) -> source.hasPermission(0); - Predicate PERMISSION_LEVEL_1 = (source) -> source.hasPermission(1); - Predicate PERMISSION_LEVEL_2 = (source) -> source.hasPermission(2); - Predicate PERMISSION_LEVEL_3 = (source) -> source.hasPermission(3); - Predicate PERMISSION_LEVEL_4 = (source) -> source.hasPermission(4); - - /** - * @param sourceStack - * @return The real command source of the specified {@code CommandSourceStack} - * @throws NoSuchFieldException - * @throws SecurityException - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @since 4.0.0 - * @deprecated Use {@link IMixinCommandSourceStack} instead {@code ((IMixinCommandSourceStack)stack).getSource()} - */ - @Deprecated(since = "4.1.5") - static CommandSource getPrivateSource(CommandSourceStack sourceStack) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - Field privateSourceField = CommandSourceStack.class.getDeclaredField("source"); - privateSourceField.setAccessible(true); - return (CommandSource) privateSourceField.get(sourceStack); + SimpleCommandExceptionType INTERNAL_ERROR = CommandExceptions.INTERNAL_ERROR; + SimpleCommandExceptionType LOGGABLE_INTERNAL_ERROR = CommandExceptions.LOGGABLE_INTERNAL_ERROR; + SimpleCommandExceptionType NOT_SERVER_ERROR = CommandExceptions.NOT_SERVER_ERROR; + SimpleCommandExceptionType NOT_DEDICATED_SERVER_ERROR = CommandExceptions.NOT_DEDICATED_SERVER_ERROR; + SimpleCommandExceptionType GET_REAL_SOURCE_REFLECTION_ERROR = CommandExceptions.GET_REAL_SOURCE_REFLECTION_ERROR; + + Predicate IS_PLAYER = CommandSourceUtils.IS_PLAYER; + Predicate PERMISSION_LEVEL_0 = CommandSourceUtils.PERMISSION_LEVEL_0; + Predicate PERMISSION_LEVEL_1 = CommandSourceUtils.PERMISSION_LEVEL_1; + Predicate PERMISSION_LEVEL_2 = CommandSourceUtils.PERMISSION_LEVEL_2; + Predicate PERMISSION_LEVEL_3 = CommandSourceUtils.PERMISSION_LEVEL_3; + Predicate PERMISSION_LEVEL_4 = CommandSourceUtils.PERMISSION_LEVEL_4; + + static CommandSource getPrivateSource(CommandSourceStack sourceStack) { + return CommandSourceUtils.getRealSourceReflection(sourceStack); } @OnlyIn(Dist.CLIENT) static LocalPlayer getLocalPlayerOrException(CommandSourceStack sourceStack) throws CommandSyntaxException { - var entity = sourceStack.getEntity(); - if (entity instanceof LocalPlayer) { - return (LocalPlayer) entity; - } - throw CommandSourceStack.ERROR_NOT_PLAYER.create(); + return CommandSourceUtils.getLocalPlayerOrException(sourceStack); } - /** - * @param nodeList List of {@link ParsedCommandNode}s, from {@link CommandContext#getNodes()} - * @param fromIndex - * @param toIndex - * @param conventToSnakeCase - * @return String that concatenates the literals (or in its snake case) of all (or some of) {@link LiteralCommandNode}s in the {@link ParsedCommandNode} list, separated by dots - * @since 5.1.1 - */ static String joinLiteralNodes(List> nodeList, int fromIndex, int toIndex, boolean conventToSnakeCase) { - return nodeList - .subList(fromIndex, toIndex) - .stream() - .map(ParsedCommandNode::getNode) - .filter((node) -> node instanceof LiteralCommandNode) - .map((node) -> (LiteralCommandNode) node) - .map(LiteralCommandNode::getLiteral) - .map((literal) -> conventToSnakeCase ? literal.replaceAll("[A-Z]", "_$0").toLowerCase() : literal) - .collect(Collectors.joining(".")); + return CommandNodeUtils.joinLiteralNodes(nodeList, fromIndex, toIndex); } - /** - * @see {@link #joinLiteralNodes(List, int, int, boolean)} - */ static String joinLiteralNodes(List> nodes, int fromIndex) { - return joinLiteralNodes(nodes, fromIndex, nodes.size(), true); + return CommandNodeUtils.joinLiteralNodes(nodes, fromIndex, nodes.size()); } - /** - * @see {@link #joinLiteralNodes(List, int, int, boolean)} - */ static String joinLiteralNodes(List> nodes) { - return joinLiteralNodes(nodes, 0, nodes.size(), true); + return CommandNodeUtils.joinLiteralNodes(nodes, 0, nodes.size()); } } diff --git a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandExceptions.java b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandExceptions.java new file mode 100644 index 00000000..162b6db9 --- /dev/null +++ b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandExceptions.java @@ -0,0 +1,23 @@ +package org.auioc.mcmod.arnicalib.utils.game.command; + +import org.auioc.mcmod.arnicalib.ArnicaLib; +import org.auioc.mcmod.arnicalib.utils.game.TextUtils; +import com.mojang.brigadier.exceptions.BuiltInExceptionProvider; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + +public class CommandExceptions { + + public static final BuiltInExceptionProvider BUILT_IN_EXCEPTIONS = CommandSyntaxException.BUILT_IN_EXCEPTIONS; + + public static final SimpleCommandExceptionType INTERNAL_ERROR = simple("command.failure.internal"); + public static final SimpleCommandExceptionType LOGGABLE_INTERNAL_ERROR = simple("command.failure.internal.loggable"); + public static final SimpleCommandExceptionType NOT_SERVER_ERROR = simple("command.failure.not_server"); + public static final SimpleCommandExceptionType NOT_DEDICATED_SERVER_ERROR = simple("command.failure.not_dedicated_server"); + public static final SimpleCommandExceptionType GET_REAL_SOURCE_REFLECTION_ERROR = simple("command.failure.get_real_source.reflection"); + + private static SimpleCommandExceptionType simple(String key) { + return new SimpleCommandExceptionType(TextUtils.translatable(ArnicaLib.i18n("command.failure.internal"))); + } + +} diff --git a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandNodeUtils.java b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandNodeUtils.java new file mode 100644 index 00000000..80776eb8 --- /dev/null +++ b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandNodeUtils.java @@ -0,0 +1,54 @@ +package org.auioc.mcmod.arnicalib.utils.game.command; + +import java.util.List; +import java.util.stream.Collectors; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.context.ParsedCommandNode; +import com.mojang.brigadier.tree.LiteralCommandNode; +import net.minecraft.commands.CommandSourceStack; + +public class CommandNodeUtils { + + public static String getLastLiteral(List> nodeList) { + for (int i = nodeList.size(); i-- > 0;) { + if (nodeList.get(i).getNode() instanceof LiteralCommandNode) { + return ((LiteralCommandNode) nodeList.get(i).getNode()).getLiteral(); + } + } + return null; + } + + /** + * @param nodeList List of {@link ParsedCommandNode}s, from {@link CommandContext#getNodes()} + * @param fromIndex + * @param toIndex + * @param conventToSnakeCase + * @return String that concatenates the literals (or in its snake case) of all (or some of) {@link LiteralCommandNode}s in the {@link ParsedCommandNode} list, separated by dots + * @since 5.1.1 + */ + public static String joinLiteralNodes(List> nodeList, int fromIndex, int toIndex) { + return nodeList + .subList(fromIndex, toIndex) + .stream() + .map(ParsedCommandNode::getNode) + .filter((node) -> node instanceof LiteralCommandNode) + .map((node) -> (LiteralCommandNode) node) + .map(LiteralCommandNode::getLiteral) + .collect(Collectors.joining(".")); + } + + /** + * @see {@link #joinLiteralNodes(List, int, int, boolean)} + */ + public static String joinLiteralNodes(List> nodes, int fromIndex) { + return joinLiteralNodes(nodes, fromIndex, nodes.size()); + } + + /** + * @see {@link #joinLiteralNodes(List, int, int, boolean)} + */ + public static String joinLiteralNodes(List> nodes) { + return joinLiteralNodes(nodes, 0, nodes.size()); + } + +} diff --git a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandSourceUtils.java b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandSourceUtils.java new file mode 100644 index 00000000..3190e9a3 --- /dev/null +++ b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/CommandSourceUtils.java @@ -0,0 +1,53 @@ +package org.auioc.mcmod.arnicalib.utils.game.command; + +import java.util.function.Predicate; +import org.auioc.mcmod.arnicalib.api.mixin.common.IMixinCommandSourceStack; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.BaseCommandBlock; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.util.ObfuscationReflectionHelper; +import net.minecraftforge.fml.util.ObfuscationReflectionHelper.UnableToAccessFieldException; + +public class CommandSourceUtils { + + public static final Predicate PERMISSION_LEVEL_0 = (sourceStack) -> sourceStack.hasPermission(0); + public static final Predicate PERMISSION_LEVEL_1 = (sourceStack) -> sourceStack.hasPermission(1); + public static final Predicate PERMISSION_LEVEL_2 = (sourceStack) -> sourceStack.hasPermission(2); + public static final Predicate PERMISSION_LEVEL_3 = (sourceStack) -> sourceStack.hasPermission(3); + public static final Predicate PERMISSION_LEVEL_4 = (sourceStack) -> sourceStack.hasPermission(4); + + public static final Predicate IS_PLAYER = (sourceStack) -> sourceStack.getEntity() instanceof Player; + public static final Predicate IS_COMMAND_BLOCK = (sourceStack) -> getRealSource(sourceStack) instanceof BaseCommandBlock; + public static final Predicate IS_DEDICATED_SERVER = (sourceStack) -> getRealSource(sourceStack) instanceof DedicatedServer; + + /** + * @param sourceStack + * @return The real command source of the specified {@code CommandSourceStack} + * @throws UnableToAccessFieldException + * @since 4.0.0 + * @deprecated Use {@link #getPrivateSource} instead + */ + @Deprecated(since = "4.1.5") + public static CommandSource getRealSourceReflection(CommandSourceStack sourceStack) { + return ObfuscationReflectionHelper.getPrivateValue(CommandSourceStack.class, sourceStack, "f_81288_"); + } + + public static CommandSource getRealSource(CommandSourceStack sourceStack) { + return ((IMixinCommandSourceStack) sourceStack).getSource(); + } + + + @OnlyIn(Dist.CLIENT) + public static LocalPlayer getLocalPlayerOrException(CommandSourceStack sourceStack) throws CommandSyntaxException { + var entity = sourceStack.getEntity(); + if (entity instanceof LocalPlayer) return (LocalPlayer) entity; + throw CommandSourceStack.ERROR_NOT_PLAYER.create(); + } + +} diff --git a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/DynamicCommandHandler.java b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/DynamicCommandHandler.java similarity index 94% rename from src/main/java/org/auioc/mcmod/arnicalib/utils/game/DynamicCommandHandler.java rename to src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/DynamicCommandHandler.java index 5ba88404..e2396736 100644 --- a/src/main/java/org/auioc/mcmod/arnicalib/utils/game/DynamicCommandHandler.java +++ b/src/main/java/org/auioc/mcmod/arnicalib/utils/game/command/DynamicCommandHandler.java @@ -1,4 +1,4 @@ -package org.auioc.mcmod.arnicalib.utils.game; +package org.auioc.mcmod.arnicalib.utils.game.command; import static org.auioc.mcmod.arnicalib.ArnicaLib.LOGGER; import java.lang.reflect.InvocationTargetException; @@ -21,7 +21,7 @@ public static int run(String className, String methodName, CommandContext