diff --git a/build.gradle b/build.gradle index e25b706..f097084 100644 --- a/build.gradle +++ b/build.gradle @@ -65,6 +65,9 @@ repositories { } metadataSources { artifact() } } + maven { + url "https://libraries.minecraft.net" + } ivy { url = "https://github.com/MartinSVK12" patternLayout { @@ -88,6 +91,8 @@ dependencies { modImplementation "ModMenu:ModMenu:2.0.0" + implementation 'com.mojang:brigadier:1.0.18' + implementation "org.slf4j:slf4j-api:1.8.0-beta4" implementation "org.apache.logging.log4j:log4j-slf4j18-impl:2.16.0" diff --git a/src/main/java/net/pedroricardo/commander/CommandParameterParser.java b/src/main/java/net/pedroricardo/commander/CommandParameterParser.java deleted file mode 100644 index 4e24cb0..0000000 --- a/src/main/java/net/pedroricardo/commander/CommandParameterParser.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.pedroricardo.commander; - -import net.pedroricardo.commander.commands.CommanderCommandParameterType; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class CommandParameterParser { - public static int getParameterInCursorIndex(String message, int cursor) { - List commandParameters = CommanderHelper.getCommandParameterListWithoutSlash(message); - return ListHelper.getStringIndexFromCharIndex(commandParameters, cursor - 1); - } - - public static String getParameterInCursor(String message, int cursor) { - List commandParameters = CommanderHelper.getCommandParameterListWithoutSlash(message); - if (commandParameters.isEmpty()) return ""; - return commandParameters.get(ListHelper.getStringIndexFromCharIndex(commandParameters, cursor - 1)); - } - - public static String replaceParameterOnString(String message, int index, String parameter) { - List parameterList = CommanderHelper.getCommandParameterList(message); - - if (parameterList.size() <= index) return message + parameter; - - parameterList.remove(index); - parameterList.add(index, parameter); - return ListHelper.join(parameterList, " "); - } - - public static int getCharIndexInEndOfParameterOnString(String message, int index) { - List parameters = CommanderHelper.getCommandParameterList(message); - List parametersBeforeIndex = parameters.subList(0, index + 1); - return ListHelper.join(parametersBeforeIndex, " ").length(); - } - - public static int getLocalIndex(List parameters, int index) { - for (CommanderCommandParameterType item : parameters) { - for (int i = 0; i < item.getExpectedParameters(); i++) { - if (index == 0) return i; - else index -= 1; - } - } - return 0; - } - - @Nullable - public static CommanderCommandParameterType getParameterFromIndex(List parameters, int index) { - for (CommanderCommandParameterType item : parameters) { - for (int i = 0; i < item.getExpectedParameters(); i++) { - if (index == 0) return item; - else index -= 1; - } - } - return null; - } -} diff --git a/src/main/java/net/pedroricardo/commander/CommandSuggester.java b/src/main/java/net/pedroricardo/commander/CommandSuggester.java deleted file mode 100644 index 592f360..0000000 --- a/src/main/java/net/pedroricardo/commander/CommandSuggester.java +++ /dev/null @@ -1,50 +0,0 @@ -package net.pedroricardo.commander; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.net.command.Command; -import net.minecraft.core.net.command.Commands; -import net.pedroricardo.commander.commands.CommanderCommand; - -import java.util.ArrayList; -import java.util.List; - -public class CommandSuggester { - public static List getSuggestedCommands(String string) { - if (string.trim().equals("")) return new ArrayList<>(); - String command = string.trim().substring(1).split(" ")[0]; - List suggestedCommands = new ArrayList<>(); - - for (Command currentCommand : Commands.commands) { - for (String currentCommandName : currentCommand.getNames()) { - if (currentCommandName.startsWith(command)) { - suggestedCommands.add(currentCommandName); - } - } - } - - return suggestedCommands; - } - - public static List getCommandSuggestions(Minecraft mc, int parameterIndex, String parameter, Command command) { - List list; - if (!(command instanceof CommanderCommand)) { - return getDefaultSuggestions(mc, parameter); - } else { - list = ((CommanderCommand)command).getCommandSuggestions(mc, parameterIndex, parameter); - } - return list; - } - - public static List getDefaultSuggestions(Minecraft mc, String parameter) { - List list = new ArrayList<>(); - mc.theWorld.players.forEach(player -> { - if (player.username.startsWith(parameter)) { - list.add(player.username); - } - }); - if (parameter.length() >= 6 && "Herobrine".startsWith(parameter) && !list.contains("Herobrine")) { - list.add("Herobrine"); - } - return list; - } -} diff --git a/src/main/java/net/pedroricardo/commander/Commander.java b/src/main/java/net/pedroricardo/commander/Commander.java index bd9daf5..fb163ac 100644 --- a/src/main/java/net/pedroricardo/commander/Commander.java +++ b/src/main/java/net/pedroricardo/commander/Commander.java @@ -1,10 +1,15 @@ package net.pedroricardo.commander; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.fabricmc.api.ModInitializer; +import net.minecraft.client.Minecraft; import net.minecraft.core.net.command.CommandHandler; import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommanderCommand; -import net.pedroricardo.commander.commands.CommandParameterTypes; +import net.pedroricardo.commander.commands.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import turniplabs.halplibe.helper.CommandHelper; @@ -20,55 +25,6 @@ public class Commander implements ModInitializer { @Override public void onInitialize() { LOGGER.info("Commander initialized."); - CommandHelper.createCommand(new CommanderCommand("testCommand1") { - @Override - public boolean execute(CommandHandler commandHandler, CommandSender commandSender, String[] strings) { - return false; - } - - @Override - public boolean opRequired(String[] strings) { - return false; - } - - @Override - public void sendCommandSyntax(CommandHandler commandHandler, CommandSender commandSender) { - - } - }.withParameter(CommandParameterTypes.FLOAT_COORDINATES)); - CommandHelper.createCommand(new CommanderCommand("testCommand2") { - @Override - public boolean execute(CommandHandler commandHandler, CommandSender commandSender, String[] strings) { - return false; - } - - @Override - public boolean opRequired(String[] strings) { - return false; - } - - @Override - public void sendCommandSyntax(CommandHandler commandHandler, CommandSender commandSender) { - - } - }.withParameter(CommandParameterTypes.INTEGER_COORDINATES)); - CommandHelper.createCommand(new CommanderCommand("testCommand3") { - @Override - public boolean execute(CommandHandler commandHandler, CommandSender commandSender, String[] strings) { - return false; - } - - @Override - public boolean opRequired(String[] strings) { - return false; - } - - @Override - public void sendCommandSyntax(CommandHandler commandHandler, CommandSender commandSender) { - - } - }.withParameter(CommandParameterTypes.BLOCK) - .withParameter(CommandParameterTypes.ITEM) - .withParameter(CommandParameterTypes.ACHIEVEMENT)); + CommanderCommandManager.init(); } } diff --git a/src/main/java/net/pedroricardo/commander/CommanderGuiManager.java b/src/main/java/net/pedroricardo/commander/CommanderGuiManager.java deleted file mode 100644 index 4ff1b1d..0000000 --- a/src/main/java/net/pedroricardo/commander/CommanderGuiManager.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.pedroricardo.commander; - -import java.util.ArrayList; -import java.util.List; - -public class CommanderGuiManager { - public static int commandIndex = 0; - public static String tablessMessage = ""; - public static int tablessCursor = -1; - public static List suggestions = new ArrayList<>(); - public static String currentError = ""; - public static int scroll = 0; - - public static boolean scroll(int amount) { - if (CommanderGuiManager.scroll + amount >= 0 && CommanderGuiManager.scroll + amount <= CommanderGuiManager.suggestions.size() - Commander.maxSuggestions) { - CommanderGuiManager.scroll += amount; - return true; - } - return false; - } -} diff --git a/src/main/java/net/pedroricardo/commander/CommanderHelper.java b/src/main/java/net/pedroricardo/commander/CommanderHelper.java index 459cbf5..6fef522 100644 --- a/src/main/java/net/pedroricardo/commander/CommanderHelper.java +++ b/src/main/java/net/pedroricardo/commander/CommanderHelper.java @@ -1,100 +1,32 @@ package net.pedroricardo.commander; +import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.suggestion.Suggestion; +import net.minecraft.client.Minecraft; import net.minecraft.client.render.FontRenderer; +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.core.net.command.Command; +import net.minecraft.core.net.command.Commands; import net.minecraft.core.util.collection.Pair; +import net.pedroricardo.commander.commands.CommanderCommandManager; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; public class CommanderHelper { - private static final List> delimiters = new ArrayList<>(); - - static { - delimiters.add(Pair.of("[", "]")); - delimiters.add(Pair.of("{", "}")); - } - - public static boolean checkForUnmatchedCharacters(String string, int i, @Nullable String currentString, @Nullable String currentImportantDelimiter) { - if (currentString != null && !currentString.isEmpty()) { - if ((!string.substring(i).contains(currentString))) { - return true; - } - } - if (currentImportantDelimiter != null && !currentImportantDelimiter.isEmpty()) { - for (Pair delimiter : delimiters) { - if (currentImportantDelimiter.equals(delimiter.getLeft()) && !string.substring(i).contains(delimiter.getRight())) { - return true; - } - } - } - return false; - } - - public static List getCommandParameterList(String message) { - List parameters = new ArrayList<>(); - String currentString = null; - String currentImportantDelimiter = null; - int lastParameterIndex = 0; - String trimmedMessage = message.trim(); - - for (int i = 0; i < trimmedMessage.length(); i++) { - if ((trimmedMessage.charAt(i) == '"' || trimmedMessage.charAt(i) == '\'') && trimmedMessage.charAt(i - 1) != '\\') { - if (currentString == null) { - currentString = String.valueOf(trimmedMessage.charAt(i)); - } else if (currentString.equals(String.valueOf(trimmedMessage.charAt(i)))) { - currentString = null; - } - } - - if (currentString == null) - for (Pair delimiter : delimiters) { - if (String.valueOf(trimmedMessage.charAt(i)).equals(delimiter.getLeft()) && currentImportantDelimiter == null) { - currentImportantDelimiter = String.valueOf(trimmedMessage.charAt(i)); - } else if (String.valueOf(trimmedMessage.charAt(i)).equals(delimiter.getRight()) && (currentImportantDelimiter != null && currentImportantDelimiter.equals(delimiter.getLeft()))) { - currentImportantDelimiter = null; - } + public static List getLegacySuggestionList(Minecraft mc, String message, int cursor, List currentSuggestions) { + List list = new ArrayList<>(); + String textBeforeCursor = message.substring(0, cursor); + if (textBeforeCursor.contains("/")) { + for (Command command : Commands.commands) { + List path = new ArrayList<>(); + path.add(command.getName()); + if (CommanderCommandManager.getDispatcher().findNode(path) == null && command.getName().startsWith(textBeforeCursor.substring(1))) { + list.add(new Suggestion(new StringRange(1, 1 + command.getName().length()), command.getName())); } - - // If the character is a space and is not between delimiters (or is after an unmatched delimiter) and the character after it is not a space (so that the space is also included in the parameter in case there are two spaces) or, instead of all those checks, it's the last character, add this as a parameter. - if (trimmedMessage.charAt(i) == ' ' && (currentImportantDelimiter == null && currentString == null || checkForUnmatchedCharacters(trimmedMessage, i, currentString, currentImportantDelimiter)) && trimmedMessage.charAt(i + 1) != ' ' || i == trimmedMessage.length() - 1) { - parameters.add(trimmedMessage.substring(lastParameterIndex, i + (i == trimmedMessage.length() - 1 ? 1 : 0))); - lastParameterIndex = i + 1; } } - - if (message.endsWith(" ")) parameters.add(""); - - return parameters; - } - - public static List getCommandParameterListWithoutSlash(String message) { - List parameters = getCommandParameterList(message); - - // Remove the leading slash from the first parameter - if (parameters.size() > 0 && parameters.get(0).startsWith("/")) { - String firstParameter = parameters.get(0); - parameters.remove(0); - parameters.add(0, firstParameter.substring(1)); - } - - return parameters; - } - - public static int getLeftMarginForSuggestions(FontRenderer fontRenderer, String message, int cursor) { - int parameterInCursor = CommandParameterParser.getParameterInCursorIndex(message, cursor); - return fontRenderer.getStringWidth(message.startsWith("/") ? (parameterInCursor == 0 ? "/" : "/ ") : "" + ListHelper.join(getCommandParameterListWithoutSlash(message).subList(0, parameterInCursor), " ")); - } - - public static int getLeftMarginForSuggestionsWithParameterIndex(FontRenderer fontRenderer, String message, int index) { - List commandParameters = CommanderHelper.getCommandParameterList(message); - return fontRenderer.getStringWidth((message.startsWith("/") && index == 0 ? "/" : "") + (index == 0 ? "" : " ") + ListHelper.join(commandParameters.subList(0, index), " ")); - } - - public static String addToIndex(String originalString, String stringToAdd, int index) { - if (index >= originalString.length()) return originalString + stringToAdd; - return originalString.substring(0, index) + - stringToAdd + - originalString.substring(index); + return list; } } diff --git a/src/main/java/net/pedroricardo/commander/ListHelper.java b/src/main/java/net/pedroricardo/commander/ListHelper.java deleted file mode 100644 index 47d6795..0000000 --- a/src/main/java/net/pedroricardo/commander/ListHelper.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.pedroricardo.commander; - -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class ListHelper { - public static int getStringIndexFromCharIndex(List list, int charIndex) { - if (charIndex < 0) return 0; - else if (charIndex >= join(list, "").length()) return list.size() - 1; - int charactersLeft = charIndex; - for (int i = 0; i < list.size(); i++) { - if (list.get(i).length() >= charactersLeft) { - return i; - } - charactersLeft -= list.get(i).length() + 1; - } - return 0; - } - - public static String join(List list) { - return join(list, ","); - } - - public static String join(List list, @Nullable String separator) { - if (separator == null) separator = ","; - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < list.size(); i++) { - if (i > 0) { - stringBuilder.append(separator); - } - stringBuilder.append(list.get(i)); - } - return stringBuilder.toString(); - } - - public static List elementsStartingWith(List list, String startsWith) { - List newList = new ArrayList<>(); - for (String element : list) { - if (element.startsWith(startsWith)) { - newList.add(element); - } - } - return newList; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommandParameterTypes.java b/src/main/java/net/pedroricardo/commander/commands/CommandParameterTypes.java deleted file mode 100644 index 5424f28..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/CommandParameterTypes.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.pedroricardo.commander.commands; - -import net.pedroricardo.commander.commands.parametertypes.*; - -public class CommandParameterTypes { - public static final CommandParameterType FLOAT_COORDINATES = new FloatCoordinatesParameterType(); - public static final CommandParameterType INTEGER_COORDINATES = new IntegerCoordinatesParameterType(); - public static final CommandParameterType BLOCK = new BlockParameterType(); - public static final CommandParameterType ITEM = new ItemParameterType(); - public static final CommandParameterType ACHIEVEMENT = new AchievementParameterType(); -// INTEGER("int", 1), -// FLOAT("float", 1), -// DOUBLE("double", 1), -// INTEGER_COORDINATES("int_coordinates", 3), -// FLOAT_COORDINATES("float_coordinates", 3), -// DOUBLE_COORDINATES("double_coordinates", 3), -// STRING("string", 1), -// ENTITY("entity", 1), -// PLAYER("player", 1), -// JSON("json", 1); - - private final String id; - private final int numberOfExpectedParameters; - - CommandParameterTypes(String id, int numberOfExpectedParameters) { - this.id = id; - this.numberOfExpectedParameters = numberOfExpectedParameters; - } - - public String getId() { - return this.id; - } - - public int getNumberOfExpectedParameters() { - return this.numberOfExpectedParameters; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommanderClientCommandSource.java b/src/main/java/net/pedroricardo/commander/commands/CommanderClientCommandSource.java new file mode 100644 index 0000000..9169bad --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/commands/CommanderClientCommandSource.java @@ -0,0 +1,40 @@ +package net.pedroricardo.commander.commands; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.entity.player.EntityPlayer; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class CommanderClientCommandSource implements CommanderCommandSource { + private final Minecraft mc; + + public CommanderClientCommandSource(Minecraft mc) { + this.mc = mc; + } + + @Override + public Collection getPlayerNames() { + List list = new ArrayList<>(); + for (EntityPlayer player : this.mc.theWorld.players) { + list.add(player.username); + } + return list; + } + + @Override + public String getType() { + return "client"; + } + + @Override + public EntityPlayer getSender() { + return this.mc.thePlayer; + } + + @Override + public boolean hasAdmin() { + return true; + } +} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommanderCommand.java b/src/main/java/net/pedroricardo/commander/commands/CommanderCommand.java deleted file mode 100644 index 8860503..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/CommanderCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.pedroricardo.commander.commands; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.net.command.Command; -import net.pedroricardo.commander.CommandParameterParser; -import net.pedroricardo.commander.ListHelper; - -import java.util.ArrayList; -import java.util.List; - -public abstract class CommanderCommand extends Command { - private final List commandParameters = new ArrayList<>(); - - public CommanderCommand(String name, String... alts) { - super(name, alts); - } - - public CommanderCommand withParameter(CommanderCommandParameterType parameter) { - this.commandParameters.add(parameter); - return this; - } - - public List getCommandParameters() { - return this.commandParameters; - } - - public List getCommandSuggestions(Minecraft mc, int parameterIndex, String parameterString) { - CommanderCommandParameterType parameter = CommandParameterParser.getParameterFromIndex(this.getCommandParameters(), parameterIndex - 1); - if (parameter == null) return new ArrayList<>(); - int localParameterIndex = CommandParameterParser.getLocalIndex(this.getCommandParameters(), parameterIndex - 1); - return ListHelper.elementsStartingWith(parameter.getSuggestions(mc, parameterIndex, localParameterIndex, parameterString), parameterString); - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommanderCommandManager.java b/src/main/java/net/pedroricardo/commander/commands/CommanderCommandManager.java new file mode 100644 index 0000000..2e3d679 --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/commands/CommanderCommandManager.java @@ -0,0 +1,45 @@ +package net.pedroricardo.commander.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.core.achievement.Achievement; +import net.pedroricardo.commander.commands.parameters.AchievementArgumentType; + +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("unchecked") +public class CommanderCommandManager { + public static int SINGLE_SUCCESS = 1; + private static final CommandDispatcher DISPATCHER = new CommandDispatcher<>(); + + static { + DISPATCHER.register((LiteralArgumentBuilder)(((LiteralArgumentBuilder)LiteralArgumentBuilder.literal("achievement")) + .then(((LiteralArgumentBuilder)LiteralArgumentBuilder.literal("grant") + ).then(RequiredArgumentBuilder.argument("achievement", AchievementArgumentType.achievementParameter()) + .executes(c -> { + List achievements = new ArrayList<>(); + achievements.add(c.getArgument("achievement", Achievement.class)); + while (achievements.get(achievements.size() - 1).parent != null) { + achievements.add(achievements.get(achievements.size() - 1).parent); + } + for (int i = 0; i < achievements.size(); i++) { + ((CommanderCommandSource)c.getSource()).getSender().triggerAchievement(achievements.get(achievements.size() - 1 - i)); + } + return SINGLE_SUCCESS; + }))))); + } + + public static void execute(String s, CommanderCommandSource commandSource) throws CommandSyntaxException { + DISPATCHER.execute(s, commandSource); + } + + public static CommandDispatcher getDispatcher() { + return DISPATCHER; + } + + public static void init() { + } +} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommanderCommandSource.java b/src/main/java/net/pedroricardo/commander/commands/CommanderCommandSource.java new file mode 100644 index 0000000..d0e9fd9 --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/commands/CommanderCommandSource.java @@ -0,0 +1,24 @@ +package net.pedroricardo.commander.commands; + +import net.minecraft.core.entity.player.EntityPlayer; + +import java.util.Collection; +import java.util.Collections; + +public interface CommanderCommandSource { + Collection getPlayerNames(); + + default Collection getChatSuggestions() { + return this.getPlayerNames(); + } + + default Collection getEntitySuggestions() { + return Collections.emptyList(); + } + + String getType(); + + EntityPlayer getSender(); + + boolean hasAdmin(); +} diff --git a/src/main/java/net/pedroricardo/commander/commands/CommanderServerCommandSource.java b/src/main/java/net/pedroricardo/commander/commands/CommanderServerCommandSource.java new file mode 100644 index 0000000..755c408 --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/commands/CommanderServerCommandSource.java @@ -0,0 +1,43 @@ +package net.pedroricardo.commander.commands; + +import net.minecraft.core.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.player.EntityPlayerMP; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class CommanderServerCommandSource implements CommanderCommandSource { + public final MinecraftServer server; + public final EntityPlayerMP player; + + public CommanderServerCommandSource(MinecraftServer server, EntityPlayerMP player) { + this.server = server; + this.player = player; + } + + @Override + public Collection getPlayerNames() { + List list = new ArrayList<>(); + for (EntityPlayer player : server.configManager.playerEntities) { + list.add(player.username); + } + return list; + } + + @Override + public String getType() { + return "server"; + } + + @Override + public EntityPlayer getSender() { + return this.player; + } + + @Override + public boolean hasAdmin() { + return false; + } +} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementArgumentType.java b/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementArgumentType.java new file mode 100644 index 0000000..849547f --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementArgumentType.java @@ -0,0 +1,52 @@ +package net.pedroricardo.commander.commands.parameters; + +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.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.core.achievement.Achievement; +import net.minecraft.core.achievement.AchievementList; +import net.minecraft.core.lang.I18n; +import net.pedroricardo.commander.mixin.StatNameAccessor; + +import java.util.concurrent.CompletableFuture; + +public class AchievementArgumentType implements ArgumentType { + public static ArgumentType achievementParameter() { + return new AchievementArgumentType(); + } + + @Override + public Achievement parse(StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + + while(reader.canRead() && isCharValid(reader.peek())) { + reader.skip(); + } + + final String string = reader.getString().substring(i, reader.getCursor()); + + for (Achievement achievement : AchievementList.achievementList) { + if (((StatNameAccessor)achievement).statName().equals(string)) { + return achievement; + } + } + throw new CommandSyntaxException(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), () -> I18n.getInstance().translateKeyAndFormat("commands.commander.achievement.invalid_achievement", string)); + } + + @Override + public CompletableFuture listSuggestions(final CommandContext context, final SuggestionsBuilder builder) { + for (Achievement achievement : AchievementList.achievementList) { + if (((StatNameAccessor)achievement).statName().startsWith(builder.getRemaining())) { + builder.suggest(((StatNameAccessor)achievement).statName()); + } + } + return builder.buildFuture(); + } + + public static boolean isCharValid(char c) { + return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c == '_' || c == ':' || c == '/' || c == '.' || c == '-' || c >= 'A' && c <= 'Z'; + } +} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementParameter.java deleted file mode 100644 index 39c444d..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/AchievementParameter.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.item.Item; -import net.minecraft.core.net.command.CommandError; -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommandParameterTypes; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public class AchievementParameter extends CommandParameter { - private final Item item; - public AchievementParameter(Item item) { - this.item = item; - } - - public Item getItem() { - return this.item; - } - - public AchievementParameter of(CommandSender commandSender, String parameter) throws CommandError { - for (Item item : Item.itemsList) { - if (item.getKey().equals(this.item.getKey())) { - return new AchievementParameter(item); - } - } - throw new CommandError("Invalid item"); - } - - @Override - public CommandParameterType getType() { - return CommandParameterTypes.ACHIEVEMENT; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/BlockParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/BlockParameter.java deleted file mode 100644 index 735630c..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/BlockParameter.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.block.Block; -import net.minecraft.core.item.Item; -import net.minecraft.core.net.command.CommandError; -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommandParameterTypes; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public class BlockParameter extends CommandParameter { - private final Block block; - public BlockParameter(Block block) { - this.block = block; - } - - public Block getBlock() { - return this.block; - } - - public BlockParameter of(CommandSender commandSender, String parameter) throws CommandError { - for (Block block : Block.blocksList) { - if (block.getKey().equals(this.block.getKey())) { - return new BlockParameter(block); - } - } - throw new CommandError("Invalid item"); - } - - @Override - public CommandParameterType getType() { - return CommandParameterTypes.BLOCK; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/CommandParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/CommandParameter.java deleted file mode 100644 index 030f4d2..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/CommandParameter.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public abstract class CommandParameter { - public abstract CommandParameter of(CommandSender commandSender, String parameter); - public abstract CommandParameterType getType(); -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/FloatCoordinatesParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/FloatCoordinatesParameter.java deleted file mode 100644 index dca3917..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/FloatCoordinatesParameter.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.net.command.CommandError; -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommandParameterTypes; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public class FloatCoordinatesParameter extends CommandParameter { - private final float x; - private final float y; - private final float z; - public FloatCoordinatesParameter(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - } - - public float getX() { - return this.x; - } - - public float getY() { - return this.y; - } - - public float getZ() { - return this.z; - } - - public FloatCoordinatesParameter of(CommandSender commandSender, String parameter) throws CommandError { - String[] splitString = parameter.split(" "); - if (splitString.length == 3) { - try { - return new FloatCoordinatesParameter(Float.parseFloat(splitString[0]), Float.parseFloat(splitString[1]), Float.parseFloat(splitString[2])); - } catch (NumberFormatException e) { - throw new CommandError("Invalid coordinates"); - } - } - throw new CommandError("Invalid coordinates"); - } - - @Override - public CommandParameterType getType() { - return CommandParameterTypes.FLOAT_COORDINATES; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/IntegerCoordinatesParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/IntegerCoordinatesParameter.java deleted file mode 100644 index 4175ed4..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/IntegerCoordinatesParameter.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.net.command.CommandError; -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommandParameterTypes; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public class IntegerCoordinatesParameter extends CommandParameter { - private final int x; - private final int y; - private final int z; - public IntegerCoordinatesParameter(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; - } - - public int getX() { - return this.x; - } - - public int getY() { - return this.y; - } - - public int getZ() { - return this.z; - } - - public IntegerCoordinatesParameter of(CommandSender commandSender, String parameter) throws CommandError { - String[] splitString = parameter.split(" "); - if (splitString.length == 3) { - try { - return new IntegerCoordinatesParameter(Integer.parseInt(splitString[0]), Integer.parseInt(splitString[1]), Integer.parseInt(splitString[2])); - } catch (NumberFormatException e) { - throw new CommandError("Invalid coordinates"); - } - } - throw new CommandError("Invalid coordinates"); - } - - @Override - public CommandParameterType getType() { - return CommandParameterTypes.INTEGER_COORDINATES; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parameters/ItemParameter.java b/src/main/java/net/pedroricardo/commander/commands/parameters/ItemParameter.java deleted file mode 100644 index 146e342..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parameters/ItemParameter.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.pedroricardo.commander.commands.parameters; - -import net.minecraft.core.item.Item; -import net.minecraft.core.net.command.CommandError; -import net.minecraft.core.net.command.CommandSender; -import net.pedroricardo.commander.commands.CommandParameterTypes; -import net.pedroricardo.commander.commands.parametertypes.CommandParameterType; - -public class ItemParameter extends CommandParameter { - private final Item item; - public ItemParameter(Item item) { - this.item = item; - } - - public Item getItem() { - return this.item; - } - - public ItemParameter of(CommandSender commandSender, String parameter) throws CommandError { - for (Item item : Item.itemsList) { - if (item.getKey().equals(this.item.getKey())) { - return new ItemParameter(item); - } - } - throw new CommandError("Invalid item"); - } - - @Override - public CommandParameterType getType() { - return CommandParameterTypes.ITEM; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/AchievementParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/AchievementParameterType.java deleted file mode 100644 index 39925d5..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/AchievementParameterType.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.achievement.Achievement; -import net.minecraft.core.achievement.AchievementList; -import net.pedroricardo.commander.mixin.StatNameAccessor; - -import java.util.ArrayList; -import java.util.List; - -public class AchievementParameterType extends CommandParameterType { - public AchievementParameterType() { - super(1); - } - - @Override - public List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter) { - List suggestions = new ArrayList<>(); - for (Achievement achievement : AchievementList.achievementList) { - suggestions.add(((StatNameAccessor)achievement).statName()); - } - return suggestions; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/BlockParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/BlockParameterType.java deleted file mode 100644 index b4e8e57..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/BlockParameterType.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.block.Block; - -import java.util.ArrayList; -import java.util.List; - -public class BlockParameterType extends CommandParameterType { - public BlockParameterType() { - super(1); - } - - @Override - public List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter) { - List suggestions = new ArrayList<>(); - for (Block block : Block.blocksList) { - if (block == null) continue; - suggestions.add(block.getKey()); - } - return suggestions; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/CommandParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/CommandParameterType.java deleted file mode 100644 index 1d49a71..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/CommandParameterType.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; -import net.pedroricardo.commander.commands.CommandParameterTypeLike; - -import java.util.List; - -public abstract class CommandParameterType extends CommandParameterTypeLike { - private final int expectedParameters; - - public CommandParameterType(int expectedParameters) { - this.expectedParameters = expectedParameters; - } - - public int getExpectedParameters() { - return this.expectedParameters; - } - - public abstract List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter); -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/FloatCoordinatesParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/FloatCoordinatesParameterType.java deleted file mode 100644 index 2e402f2..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/FloatCoordinatesParameterType.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -public class FloatCoordinatesParameterType extends CommandParameterType { - public FloatCoordinatesParameterType() { - super(3); - } - - /* - public static FloatCoordinatesParameterType of(String str) { - String[] splitString = str.split(" "); - if (splitString.length == 3) { - try { - return new FloatCoordinatesParameterType(Float.parseFloat(splitString[0]), Float.parseFloat(splitString[1]), Float.parseFloat(splitString[2])); - } catch (NumberFormatException e) { - throw new CommandError("Invalid coordinates"); - } - } - throw new CommandError("Invalid coordinates"); - } - */ - - @Override - public List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter) { - List parameters = new ArrayList<>(); - DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); - DecimalFormat df = new DecimalFormat("0.######", symbols); - switch (localIndex) { - case 2: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) - parameters.add(df.format(mc.objectMouseOver.entity.x)); - else - parameters.add(df.format(mc.objectMouseOver.x)); - } else { - parameters.add(df.format(mc.thePlayer.z)); - } - break; - case 1: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) { - parameters.add(df.format(mc.objectMouseOver.entity.y)); - parameters.add(df.format(mc.objectMouseOver.entity.y) + " " + df.format(mc.objectMouseOver.entity.z)); - } else { - parameters.add(df.format(mc.objectMouseOver.y)); - parameters.add(df.format(mc.objectMouseOver.y) + " " + df.format(mc.objectMouseOver.z)); - } - } else { - parameters.add(df.format(mc.thePlayer.y)); - parameters.add(df.format(mc.thePlayer.y) + " " + df.format(mc.thePlayer.z)); - } - break; - default: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) { - parameters.add(df.format(mc.objectMouseOver.entity.x)); - parameters.add(df.format(mc.objectMouseOver.entity.x) + " " + df.format(mc.objectMouseOver.entity.y)); - parameters.add(df.format(mc.objectMouseOver.entity.x) + " " + df.format(mc.objectMouseOver.entity.y) + " " + df.format(mc.objectMouseOver.entity.z)); - } else { - parameters.add(df.format(mc.objectMouseOver.x)); - parameters.add(df.format(mc.objectMouseOver.x) + " " + df.format(mc.objectMouseOver.y)); - parameters.add(df.format(mc.objectMouseOver.x) + " " + df.format(mc.objectMouseOver.y) + " " + df.format(mc.objectMouseOver.z)); - } - } else { - parameters.add(df.format(mc.thePlayer.x)); - parameters.add(df.format(mc.thePlayer.x) + " " + df.format(mc.thePlayer.y)); - parameters.add(df.format(mc.thePlayer.x) + " " + df.format(mc.thePlayer.y) + " " + df.format(mc.thePlayer.z)); - } - } - return parameters; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/IntegerCoordinatesParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/IntegerCoordinatesParameterType.java deleted file mode 100644 index 3f43080..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/IntegerCoordinatesParameterType.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; - -import java.util.ArrayList; -import java.util.List; - -public class IntegerCoordinatesParameterType extends CommandParameterType { - public IntegerCoordinatesParameterType() { - super(3); - } - - @Override - public List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter) { - List parameters = new ArrayList<>(); - switch (localIndex) { - case 2: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.entity.x))); - else - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.x))); - } else { - parameters.add(String.valueOf(Math.round(mc.thePlayer.z))); - } - break; - case 1: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) { - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.entity.y))); - parameters.add(Math.round(mc.objectMouseOver.entity.y) + " " + Math.round(mc.objectMouseOver.entity.z)); - } else { - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.y))); - parameters.add(Math.round(mc.objectMouseOver.y) + " " + Math.round(mc.objectMouseOver.z)); - } - } else { - parameters.add(String.valueOf(Math.round(mc.thePlayer.y))); - parameters.add(Math.round(mc.thePlayer.y) + " " + Math.round(mc.thePlayer.z)); - } - break; - default: - if (mc.objectMouseOver != null) { - if (mc.objectMouseOver.entity != null) { - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.entity.x))); - parameters.add(Math.round(mc.objectMouseOver.entity.x) + " " + Math.round(mc.objectMouseOver.entity.y)); - parameters.add(Math.round(mc.objectMouseOver.entity.x) + " " + Math.round(mc.objectMouseOver.entity.y) + " " + Math.round(mc.objectMouseOver.entity.z)); - } else { - parameters.add(String.valueOf(Math.round(mc.objectMouseOver.x))); - parameters.add(Math.round(mc.objectMouseOver.x) + " " + Math.round(mc.objectMouseOver.y)); - parameters.add(Math.round(mc.objectMouseOver.x) + " " + Math.round(mc.objectMouseOver.y) + " " + Math.round(mc.objectMouseOver.z)); - } - } else { - parameters.add(String.valueOf(Math.round(mc.thePlayer.x))); - parameters.add(Math.round(mc.thePlayer.x) + " " + Math.round(mc.thePlayer.y)); - parameters.add(Math.round(mc.thePlayer.x) + " " + Math.round(mc.thePlayer.y) + " " + Math.round(mc.thePlayer.z)); - } - } - return parameters; - } -} diff --git a/src/main/java/net/pedroricardo/commander/commands/parametertypes/ItemParameterType.java b/src/main/java/net/pedroricardo/commander/commands/parametertypes/ItemParameterType.java deleted file mode 100644 index 23428b9..0000000 --- a/src/main/java/net/pedroricardo/commander/commands/parametertypes/ItemParameterType.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.pedroricardo.commander.commands.parametertypes; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.item.Item; - -import java.util.ArrayList; -import java.util.List; - -public class ItemParameterType extends CommandParameterType { - public ItemParameterType() { - super(1); - } - - @Override - public List getSuggestions(Minecraft mc, int parameterIndex, int localIndex, String parameter) { - List suggestions = new ArrayList<>(); - for (Item item : Item.itemsList) { - if (item == null) continue; - suggestions.add(item.getKey()); - } - return suggestions; - } -} diff --git a/src/main/java/net/pedroricardo/commander/gui/GuiChatSuggestions.java b/src/main/java/net/pedroricardo/commander/gui/GuiChatSuggestions.java index 71e94c7..dc60b23 100644 --- a/src/main/java/net/pedroricardo/commander/gui/GuiChatSuggestions.java +++ b/src/main/java/net/pedroricardo/commander/gui/GuiChatSuggestions.java @@ -1,33 +1,47 @@ package net.pedroricardo.commander.gui; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.suggestion.Suggestion; +import com.mojang.brigadier.suggestion.Suggestions; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.text.TextFieldEditor; import net.minecraft.client.render.FontRenderer; -import net.minecraft.core.lang.I18n; -import net.minecraft.core.net.command.Commands; import net.pedroricardo.commander.*; +import net.pedroricardo.commander.commands.CommanderClientCommandSource; +import net.pedroricardo.commander.commands.CommanderCommandManager; +import net.pedroricardo.commander.commands.CommanderCommandSource; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.List; import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; public class GuiChatSuggestions extends Gui { private final TextFieldEditor editor; private final GuiChat chat; private final Minecraft mc; private final FontRenderer fontRenderer; + private final CommanderClientCommandSource commandSource; + @Nullable + private ParseResults parseResults; + @Nullable + private CompletableFuture pendingSuggestions; private int commandIndex = -1; private String tablessMessage; private int tablessCursor; private String currentError = ""; - private List suggestions = new ArrayList<>(); + private List suggestions = new ArrayList<>(); private int scroll = 0; public GuiChatSuggestions(Minecraft mc, TextFieldEditor textFieldEditor, GuiChat chat) { this.mc = mc; this.fontRenderer = this.mc.fontRenderer; + this.commandSource = new CommanderClientCommandSource(this.mc); this.editor = textFieldEditor; this.chat = chat; this.tablessMessage = this.chat.getText(); @@ -35,43 +49,44 @@ public GuiChatSuggestions(Minecraft mc, TextFieldEditor textFieldEditor, GuiChat } public void drawScreen() { - if (!this.currentError.isEmpty()) { - this.renderSingleSuggestionLine(this.mc.fontRenderer, "§e" + this.currentError); - } else if (!this.suggestions.isEmpty()) { + if (!this.suggestions.isEmpty()) { this.renderSuggestions(this.fontRenderer, this.tablessMessage, this.tablessCursor); + } else if (this.parseResults != null && !this.parseResults.getExceptions().isEmpty()) { + for (Exception e : this.parseResults.getExceptions().values()) { + this.renderSingleSuggestionLine(this.mc.fontRenderer, "§e" + e.getMessage()); + } } } private void renderSuggestions(FontRenderer fontRenderer, String message, int cursor) { int height = this.mc.resolution.scaledHeight; int mouseX = GuiHelper.getScaledMouseX(this.mc); - int mouseY = GuiHelper.getScaledMouseY(this.mc); + int mouseY = GuiHelper.getScaledMouseY(this.mc) - 1; - int parameterInCursor = CommandParameterParser.getParameterInCursorIndex(message, cursor); + int parameterStart = this.suggestions.get(0).getRange().getStart(); int leftMargin = 2; if (Commander.suggestionsFollowParameters) - leftMargin += CommanderHelper.getLeftMarginForSuggestionsWithParameterIndex(fontRenderer, message, parameterInCursor) + 1; + leftMargin += fontRenderer.getStringWidth(message.substring(0, parameterStart)) + 1; int largestSuggestion = 0; - for (String suggestion : this.suggestions) - if (fontRenderer.getStringWidth(suggestion) > largestSuggestion) largestSuggestion = fontRenderer.getStringWidth(suggestion); + for (Suggestion suggestion : this.suggestions) + if (fontRenderer.getStringWidth(suggestion.getText()) > largestSuggestion) largestSuggestion = fontRenderer.getStringWidth(suggestion.getText()); this.drawRect(leftMargin, height - 15 - (Math.min(this.suggestions.size(), Commander.maxSuggestions) * 12), largestSuggestion + leftMargin + 1, height - 15, Integer.MIN_VALUE); if (this.scroll < this.suggestions.size() - Commander.maxSuggestions) GuiHelper.drawDottedRect(this, leftMargin, height - 15, largestSuggestion + leftMargin + 1, height - 14, Color.WHITE.getRGB(), 1); if (this.scroll != 0) GuiHelper.drawDottedRect(this, leftMargin, height - 16 - (Commander.maxSuggestions * 12), largestSuggestion + leftMargin + 1, height - 15 - (Commander.maxSuggestions * 12), Color.WHITE.getRGB(), 1); for (int i = 0; i < Math.min(this.suggestions.size(), Commander.maxSuggestions); i++) { - String suggestion = this.suggestions.get(i + this.scroll); + String suggestionText = this.suggestions.get(i + this.scroll).getText(); int suggestionHeight = 12 * (-i + Math.min(this.suggestions.size(), Commander.maxSuggestions) - 1) + 25; String colorCode; if (i + this.scroll == this.commandIndex || i + this.scroll == this.getIndexOfSuggestionBeingHoveredOver(mouseX, mouseY)) { colorCode = "§4"; } else { - colorCode = "§0"; - suggestion = CommanderHelper.addToIndex(suggestion, "§8", CommanderHelper.getCommandParameterListWithoutSlash(this.tablessMessage).get(parameterInCursor).length()); + colorCode = "§8"; } - fontRenderer.drawStringWithShadow(colorCode + suggestion, leftMargin + 1, height - suggestionHeight, 0xE0E0E0); + fontRenderer.drawStringWithShadow(colorCode + suggestionText, leftMargin + 1, height - suggestionHeight, 0xE0E0E0); } } @@ -85,49 +100,42 @@ private void renderSingleSuggestionLine(FontRenderer fontRenderer, String text) } public void keyTyped(char c, int key) { - String parameterInCursor; - int parameterInCursorIndex; - if (key != 15 && (Character.isISOControl(c) || this.chat.isCharacterAllowed(c))) { + if (key != 15) { this.resetAllManagerVariables(); - parameterInCursor = CommandParameterParser.getParameterInCursor(this.tablessMessage, this.tablessCursor); - parameterInCursorIndex = CommandParameterParser.getParameterInCursorIndex(this.tablessMessage, this.tablessCursor); - if (this.tablessMessage.startsWith("/")) { - if (parameterInCursorIndex == 0) { - this.suggestions = CommandSuggester.getSuggestedCommands(this.tablessMessage); - if (this.suggestions.isEmpty()) { - this.currentError = I18n.getInstance().translateKey("commands.commander.no_commands_available"); - } - } else { - this.suggestions = CommandSuggester.getCommandSuggestions(this.mc, parameterInCursorIndex, parameterInCursor, Commands.getCommand(CommanderHelper.getCommandParameterListWithoutSlash(this.tablessMessage).get(0))); - } - } else { - this.suggestions = new ArrayList<>(); + String text = this.editor.getText(); + int cursor = this.editor.getCursor(); + if (this.parseResults != null && !this.parseResults.getReader().getString().equals(text)) { + this.parseResults = null; } - } else if (key == 15) { - this.editor.setText(this.tablessMessage); - this.editor.setCursor(this.tablessCursor); - - parameterInCursor = CommandParameterParser.getParameterInCursor(this.tablessMessage, this.tablessCursor); - parameterInCursorIndex = CommandParameterParser.getParameterInCursorIndex(this.tablessMessage, this.tablessCursor); - if (!this.tablessMessage.startsWith("/")) { - this.suggestions = CommandSuggester.getDefaultSuggestions(this.mc, parameterInCursor); - if (!this.suggestions.isEmpty()) { - this.cycleThroughSuggestions(parameterInCursorIndex); + + StringReader stringReader = new StringReader(text); + boolean bl = stringReader.canRead() && stringReader.peek() == '/'; + if (bl) { + stringReader.skip(); + CommandDispatcher dispatcher = CommanderCommandManager.getDispatcher(); + if (this.parseResults == null) { + this.parseResults = dispatcher.parse(stringReader, this.commandSource); } - } else { - if (parameterInCursorIndex == 0) { - if (!this.suggestions.isEmpty()) { - this.cycleThroughSuggestions(parameterInCursorIndex, "/"); - } else { - this.currentError = I18n.getInstance().translateKey("commands.commander.no_commands_available"); - } - } else { - this.suggestions = CommandSuggester.getCommandSuggestions(this.mc, parameterInCursorIndex, parameterInCursor, Commands.getCommand(CommanderHelper.getCommandParameterListWithoutSlash(this.tablessMessage).get(0))); - if (!this.suggestions.isEmpty()) { - this.cycleThroughSuggestions(parameterInCursorIndex); - } + if (cursor >= 1) { + this.pendingSuggestions = dispatcher.getCompletionSuggestions(this.parseResults, cursor); + this.pendingSuggestions.thenRun(() -> { + if (this.pendingSuggestions.isDone()) { + this.updateSuggestions(); + } + }); } } + } else { + this.cycleThroughSuggestions(); + } + } + + private void updateSuggestions() { + this.suggestions = new ArrayList<>(); + if (this.pendingSuggestions != null && this.pendingSuggestions.isDone()) { + Suggestions suggestions = this.pendingSuggestions.join(); + this.suggestions.addAll(suggestions.getList()); + this.suggestions.addAll(CommanderHelper.getLegacySuggestionList(this.mc, this.tablessMessage, this.tablessCursor, this.suggestions)); } } @@ -141,32 +149,32 @@ public void updateScreen(int dWheel) { public void mouseClicked(int x, int y, int button) { if (isHoveringOverSuggestions(x, y) && button == 0) { - int parameterInCursorIndex = CommandParameterParser.getParameterInCursorIndex(this.tablessMessage, this.tablessCursor); - String prefix = this.tablessMessage.startsWith("/") && parameterInCursorIndex == 0 ? "/" : ""; - this.cycleToSuggestion(this.getIndexOfSuggestionBeingHoveredOver(x, y), parameterInCursorIndex, prefix); + this.cycleToSuggestion(this.getIndexOfSuggestionBeingHoveredOver(x, y)); } } - private boolean isHoveringOverSuggestions(int cursorX, int cursorY) { + public boolean isHoveringOverSuggestions(int cursorX, int cursorY) { return this.getIndexOfSuggestionBeingHoveredOver(cursorX, cursorY) != -1; } - private int getIndexOfSuggestionBeingHoveredOver(int cursorX, int cursorY) { + public int getIndexOfSuggestionBeingHoveredOver(int cursorX, int cursorY) { + if (this.suggestions.size() == 0) return -1; int height = this.mc.resolution.scaledHeight; - int parameterInCursor = CommandParameterParser.getParameterInCursorIndex(this.tablessMessage, this.tablessCursor); + + int parameterStart = this.suggestions.get(0).getRange().getStart(); int minX = 2; if (Commander.suggestionsFollowParameters) - minX += CommanderHelper.getLeftMarginForSuggestionsWithParameterIndex(this.fontRenderer, this.tablessMessage, parameterInCursor) + 1; + minX += fontRenderer.getStringWidth(this.tablessMessage.substring(0, parameterStart)) + 1; int largestSuggestion = 0; - for (String suggestion : this.suggestions) - if (this.fontRenderer.getStringWidth(suggestion) > largestSuggestion) largestSuggestion = this.fontRenderer.getStringWidth(suggestion); + for (Suggestion suggestion : this.suggestions) + if (this.fontRenderer.getStringWidth(suggestion.getText()) > largestSuggestion) largestSuggestion = this.fontRenderer.getStringWidth(suggestion.getText()); int maxX = largestSuggestion + minX + 1; for (int i = 0; i < Math.min(this.suggestions.size(), Commander.maxSuggestions); i++) { - int minY = height - 14 - ((Math.min(this.suggestions.size(), Commander.maxSuggestions) - i) * 12); - int maxY = height - 2 - ((Math.min(this.suggestions.size(), Commander.maxSuggestions) - i) * 12); + int minY = height - 15 - ((Math.min(this.suggestions.size(), Commander.maxSuggestions) - i) * 12); + int maxY = height - 3 - ((Math.min(this.suggestions.size(), Commander.maxSuggestions) - i) * 12); if (cursorX >= minX && cursorX < maxX && cursorY >= minY && cursorY < maxY) { return i + this.scroll; @@ -184,35 +192,6 @@ private void resetAllManagerVariables() { this.scroll = 0; } - private void cycleThroughSuggestions(int parameterInCursorIndex) { - this.cycleThroughSuggestions(parameterInCursorIndex, ""); - } - - private void cycleThroughSuggestions(int parameterInCursorIndex, String parameterPrefix) { - this.cycleToSuggestion(this.commandIndex + 1, parameterInCursorIndex, parameterPrefix); - } - - private void cycleToSuggestion(int suggestionIndex, int parameterInCursorIndex) { - this.cycleToSuggestion(suggestionIndex, parameterInCursorIndex, ""); - } - - private void cycleToSuggestion(int suggestionIndex, int parameterInCursorIndex, String parameterPrefix) { - this.commandIndex = suggestionIndex % this.suggestions.size(); - String newString = CommandParameterParser.replaceParameterOnString(this.tablessMessage, parameterInCursorIndex, parameterPrefix + this.suggestions.get(this.commandIndex)); - String parameterInCursor = ""; - if (!CommanderHelper.getCommandParameterList(newString).isEmpty()) { - parameterInCursor = CommanderHelper.getCommandParameterList(newString).get(parameterInCursorIndex); - } - this.editor.setText(newString); - this.editor.setCursor(CommandParameterParser.getCharIndexInEndOfParameterOnString(newString, parameterInCursorIndex) - parameterInCursor.length() + parameterPrefix.length() + this.suggestions.get(this.commandIndex).length()); - - if (this.commandIndex < this.scroll) { - this.scroll = this.commandIndex; - } else if (this.scroll + Commander.maxSuggestions - 1 < this.commandIndex) { - this.scroll = this.commandIndex - (Commander.maxSuggestions - 1); - } - } - public boolean scroll(int amount) { if (this.scroll + amount >= 0 && this.scroll + amount <= this.suggestions.size() - Commander.maxSuggestions) { this.scroll += amount; @@ -221,7 +200,24 @@ public boolean scroll(int amount) { return false; } - public List getSuggestions() { + public void cycleThroughSuggestions() { + this.cycleToSuggestion(this.commandIndex + 1); + } + + public void cycleToSuggestion(int index) { + if (this.suggestions.size() == 0) return; + this.commandIndex = index % this.suggestions.size(); + Suggestion suggestion = this.suggestions.get(this.commandIndex); + this.editor.setText(suggestion.apply(this.tablessMessage)); + this.editor.setCursor(suggestion.getRange().getStart() + suggestion.getText().length()); + if (this.commandIndex >= this.scroll + Commander.maxSuggestions) { + this.scroll = this.commandIndex - Commander.maxSuggestions + 1; + } else if (this.commandIndex < this.scroll) { + this.scroll = this.commandIndex; + } + } + + public List getSuggestions() { return new ArrayList<>(this.suggestions); } diff --git a/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandNetServerHandlerMixin.java b/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandNetServerHandlerMixin.java new file mode 100644 index 0000000..df84936 --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandNetServerHandlerMixin.java @@ -0,0 +1,39 @@ +package net.pedroricardo.commander.mixin; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.core.net.packet.Packet3Chat; +import net.minecraft.core.util.helper.AES; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.entity.player.EntityPlayerMP; +import net.minecraft.server.net.handler.NetServerHandler; +import net.pedroricardo.commander.commands.CommanderCommandManager; +import net.pedroricardo.commander.commands.CommanderServerCommandSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = NetServerHandler.class, remap = false) +public class PreferCommanderCommandNetServerHandlerMixin { + @Mixin(value = NetServerHandler.class, remap = false) + private interface NetServerHandlerAccessor { + @Accessor("mcServer") + MinecraftServer mcServer(); + + @Accessor("playerEntity") + EntityPlayerMP playerEntity(); + } + + @Inject(method = "handleSlashCommand", at = @At("HEAD"), cancellable = true) + private void handleSlashCommand(String s, CallbackInfo ci) { + CommanderServerCommandSource serverCommandSource = new CommanderServerCommandSource(((NetServerHandlerAccessor)((NetServerHandler)(Object)this)).mcServer(), ((NetServerHandlerAccessor)((NetServerHandler)(Object)this)).playerEntity()); + try { + CommanderCommandManager.execute(s, serverCommandSource); + ci.cancel(); + } catch (CommandSyntaxException e) { + if (e.getType() != CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()) + ((NetServerHandlerAccessor)((NetServerHandler)(Object)this)).playerEntity().playerNetServerHandler.sendPacket(new Packet3Chat(e.getMessage(), AES.keyChain.get(((NetServerHandlerAccessor)((NetServerHandler)(Object)this)).playerEntity().username))); + } + } +} diff --git a/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandPlayerSPMixin.java b/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandPlayerSPMixin.java new file mode 100644 index 0000000..5fe1f0a --- /dev/null +++ b/src/main/java/net/pedroricardo/commander/mixin/PreferCommanderCommandPlayerSPMixin.java @@ -0,0 +1,41 @@ +package net.pedroricardo.commander.mixin; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.EntityPlayerSP; +import net.minecraft.core.net.command.TextFormatting; +import net.minecraft.core.net.packet.Packet3Chat; +import net.minecraft.core.util.helper.AES; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.net.handler.NetServerHandler; +import net.pedroricardo.commander.commands.CommanderClientCommandSource; +import net.pedroricardo.commander.commands.CommanderCommandManager; +import net.pedroricardo.commander.commands.CommanderServerCommandSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = EntityPlayerSP.class, remap = false) +public class PreferCommanderCommandPlayerSPMixin { + @Mixin(value = EntityPlayerSP.class, remap = false) + private interface EntityPlayerSPAccessor { + @Accessor("mc") + Minecraft mc(); + } + + @Inject(method = "sendChatMessage", at = @At(value = "INVOKE", target = "Ljava/lang/System;arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V", ordinal = 0, shift = At.Shift.BEFORE), + cancellable = true) + private void sendChatMessage(String s, CallbackInfo ci) { + String command = s.substring(1); + CommanderClientCommandSource clientCommandSource = new CommanderClientCommandSource(((EntityPlayerSPAccessor)((EntityPlayerSP)(Object)this)).mc()); + try { + CommanderCommandManager.execute(command, clientCommandSource); + ci.cancel(); + } catch (CommandSyntaxException e) { + if (e.getType() != CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()) + ((EntityPlayerSPAccessor)((EntityPlayerSP)(Object)this)).mc().thePlayer.sender.sendMessage(TextFormatting.RED + e.getMessage()); + } + } +} diff --git a/src/main/java/net/pedroricardo/commander/mixin/ShowCommandSuggestionsMixin.java b/src/main/java/net/pedroricardo/commander/mixin/ShowCommandSuggestionsMixin.java index 4406b06..e2be18c 100644 --- a/src/main/java/net/pedroricardo/commander/mixin/ShowCommandSuggestionsMixin.java +++ b/src/main/java/net/pedroricardo/commander/mixin/ShowCommandSuggestionsMixin.java @@ -5,8 +5,6 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.text.TextFieldEditor; import net.minecraft.client.render.FontRenderer; -import net.pedroricardo.commander.CommandParameterParser; -import net.pedroricardo.commander.CommanderHelper; import net.pedroricardo.commander.gui.GuiChatSuggestions; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -41,9 +39,11 @@ private void initGui(CallbackInfo ci) { @Inject(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;drawString(Lnet/minecraft/client/render/FontRenderer;Ljava/lang/String;III)V", ordinal = 0, shift = At.Shift.BEFORE)) private void drawSuggestionPreview(int x, int y, float renderPartialTicks, CallbackInfo ci) { - int parameterInCursorIndex = CommandParameterParser.getParameterInCursorIndex(this.suggestionsGui.getMessage(), this.suggestionsGui.getCursor()); - int leftMargin = CommanderHelper.getLeftMarginForSuggestionsWithParameterIndex(((GuiScreenAccessor)((GuiChat)(Object)this)).fontRenderer(), this.suggestionsGui.getMessage(), parameterInCursorIndex) + 3; - if (!this.suggestionsGui.getSuggestions().isEmpty() && this.suggestionsGui.getCommandIndex() == -1 && parameterInCursorIndex == CommanderHelper.getCommandParameterList(this.suggestionsGui.getMessage()).size() - 1) ((GuiScreenAccessor)((GuiChat)(Object)this)).fontRenderer().drawStringWithShadow("§8" + this.suggestionsGui.getSuggestions().get(0), leftMargin + 1, ((GuiChat)(Object)this).height - 12, 0xE0E0E0); + //if (!this.suggestionsGui.getSuggestions().isEmpty() && this.suggestionsGui.getSuggestions().get(0).) + + //int parameterInCursorIndex = CommandParameterParser.getParameterInCursorIndex(this.suggestionsGui.getMessage(), this.suggestionsGui.getCursor()); + //int leftMargin = CommanderHelper.getLeftMarginForSuggestionsWithParameterIndex(((GuiScreenAccessor)((GuiChat)(Object)this)).fontRenderer(), this.suggestionsGui.getMessage(), parameterInCursorIndex) + 3; + //if (!this.suggestionsGui.getSuggestions().isEmpty() && this.suggestionsGui.getCommandIndex() == -1 && parameterInCursorIndex == CommanderHelper.getCommandParameterList(this.suggestionsGui.getMessage()).size() - 1) ((GuiScreenAccessor)((GuiChat)(Object)this)).fontRenderer().drawStringWithShadow("§8" + this.suggestionsGui.getSuggestions().get(0), leftMargin + 1, ((GuiChat)(Object)this).height - 12, 0xE0E0E0); } @Inject(method = "drawScreen", at = @At("TAIL")) @@ -52,7 +52,7 @@ private void drawSuggestionsGuiScreen(int x, int y, float renderPartialTicks, Ca } @Inject(method = "keyTyped", at = @At("RETURN")) - public void keyTyped(char c, int key, int mouseX, int mouseY, CallbackInfo ci) { + private void keyTyped(char c, int key, int mouseX, int mouseY, CallbackInfo ci) { this.suggestionsGui.keyTyped(c, key); } diff --git a/src/main/resources/commander.mixins.json b/src/main/resources/commander.mixins.json index f06de83..7bbdebe 100644 --- a/src/main/resources/commander.mixins.json +++ b/src/main/resources/commander.mixins.json @@ -4,6 +4,10 @@ "package": "net.pedroricardo.commander.mixin", "compatibilityLevel": "JAVA_8", "mixins": [ + "PreferCommanderCommandNetServerHandlerMixin", + "PreferCommanderCommandNetServerHandlerMixin$NetServerHandlerAccessor", + "PreferCommanderCommandPlayerSPMixin", + "PreferCommanderCommandPlayerSPMixin$EntityPlayerSPAccessor", "ShowCommandSuggestionsMixin", "ShowCommandSuggestionsMixin$GuiScreenAccessor", "ShowCommandSuggestionsMixin$TextFieldEditorAccessor", diff --git a/src/main/resources/lang/commander/en_US.lang b/src/main/resources/lang/commander/en_US.lang index c743239..b00e109 100644 --- a/src/main/resources/lang/commander/en_US.lang +++ b/src/main/resources/lang/commander/en_US.lang @@ -1,4 +1 @@ -commands.commander.available_commands=Available commands: -commands.commander.teleport.invalid_location=Invalid location -commands.commander.invalid_selector=Invalid selector -commands.commander.no_commands_available=No commands available \ No newline at end of file +commands.commander.achievement.invalid_achievement=Invalid achievement: %s \ No newline at end of file