From 2a0d9e8dacac9f5930c7d6e9ced24867ff4a92ea Mon Sep 17 00:00:00 2001 From: SizableShrimp <29855886+SizableShrimp@users.noreply.github.com> Date: Mon, 15 Mar 2021 15:20:08 -0500 Subject: [PATCH] Fix datapack exception related to EnumArgument with siblings (#7686) Invalid enum constants are now properly thrown as a CommandSyntaxException --- .../server/command/EnumArgument.java | 12 +++- .../resources/assets/forge/lang/en_us.json | 1 + .../debug/command/EnumArgumentTest.java | 66 +++++++++++++++++++ .../debug/command/package-info.java | 26 ++++++++ src/test/resources/META-INF/mods.toml | 2 + 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/test/java/net/minecraftforge/debug/command/EnumArgumentTest.java create mode 100644 src/test/java/net/minecraftforge/debug/command/package-info.java diff --git a/src/main/java/net/minecraftforge/server/command/EnumArgument.java b/src/main/java/net/minecraftforge/server/command/EnumArgument.java index a6411d3eba..3f785986f0 100644 --- a/src/main/java/net/minecraftforge/server/command/EnumArgument.java +++ b/src/main/java/net/minecraftforge/server/command/EnumArgument.java @@ -24,18 +24,23 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.command.ISuggestionProvider; import net.minecraft.command.arguments.IArgumentSerializer; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.text.TranslationTextComponent; +import java.util.Arrays; import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; public class EnumArgument> implements ArgumentType { + private static final Dynamic2CommandExceptionType INVALID_ENUM = new Dynamic2CommandExceptionType( + (found, constants) -> new TranslationTextComponent("commands.forge.arguments.enum.invalid", constants, found)); private final Class enumClass; public static > EnumArgument enumArgument(Class enumClass) { @@ -47,7 +52,12 @@ public class EnumArgument> implements ArgumentType { @Override public T parse(final StringReader reader) throws CommandSyntaxException { - return Enum.valueOf(enumClass, reader.readUnquotedString()); + String name = reader.readUnquotedString(); + try { + return Enum.valueOf(enumClass, name); + } catch (IllegalArgumentException e) { + throw INVALID_ENUM.createWithContext(reader, name, Arrays.toString(enumClass.getEnumConstants())); + } } @Override diff --git a/src/main/resources/assets/forge/lang/en_us.json b/src/main/resources/assets/forge/lang/en_us.json index 930800090c..bb42ccf279 100644 --- a/src/main/resources/assets/forge/lang/en_us.json +++ b/src/main/resources/assets/forge/lang/en_us.json @@ -82,6 +82,7 @@ "fml.messages.version.restriction.bounded.lowerexclusive":"above {0}, and {1} or below", "fml.messages.version.restriction.bounded.upperexclusive":"{0} or above, and below {1}", + "commands.forge.arguments.enum.invalid": "Enum constant must be one of {0}, found {1}", "commands.forge.dimensions.list": "Currently registered dimensions by type:", "commands.forge.entity.list.invalid": "Invalid filter, does not match any entities. Use /forge entity list for a proper list", "commands.forge.entity.list.invalidworld": "Could not load world for dimension {0}. Please select a valid dimension.", diff --git a/src/test/java/net/minecraftforge/debug/command/EnumArgumentTest.java b/src/test/java/net/minecraftforge/debug/command/EnumArgumentTest.java new file mode 100644 index 0000000000..1c2361452f --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/command/EnumArgumentTest.java @@ -0,0 +1,66 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.command; + +import net.minecraft.command.Commands; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.server.command.EnumArgument; + +import com.mojang.brigadier.arguments.StringArgumentType; + +@Mod("enum_argument_test") +public class EnumArgumentTest +{ + public static final boolean ENABLE = true; + + public EnumArgumentTest() + { + if (ENABLE) + MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public void registerCommands(RegisterCommandsEvent event) + { + event.getDispatcher().register(Commands.literal("enumargumenttest") + .then(Commands.argument("string", StringArgumentType.string()) + .executes(context -> { + context.getSource().sendSuccess(new StringTextComponent("string: " + StringArgumentType.getString(context, "string")), false); + + return 1; + })) + .then(Commands.argument("enum", EnumArgument.enumArgument(ExampleEnum.class)) + .executes(context -> { + context.getSource() + .sendSuccess(new StringTextComponent("enum: " + context.getArgument("enum", ExampleEnum.class)), false); + + return 1; + }))); + } + + public enum ExampleEnum + { + A, B + } +} diff --git a/src/test/java/net/minecraftforge/debug/command/package-info.java b/src/test/java/net/minecraftforge/debug/command/package-info.java new file mode 100644 index 0000000000..b14d5058ed --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/command/package-info.java @@ -0,0 +1,26 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +package net.minecraftforge.debug.command; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index af92e03fb1..29ff48a8fd 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -118,3 +118,5 @@ license="LGPL v2.1" modId="worldgen_registry_desync_test" [[mods]] modId="add_entity_attribute_test" +[[mods]] + modId="enum_argument_test"