diff --git a/src/main/java/me/alpha432/oyvey/features/commands/ArgumentSuggestions.java b/src/main/java/me/alpha432/oyvey/features/commands/ArgumentSuggestions.java new file mode 100644 index 0000000..df39a4a --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/features/commands/ArgumentSuggestions.java @@ -0,0 +1,37 @@ +package me.alpha432.oyvey.features.commands; + +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.stream.Stream; + +public final class ArgumentSuggestions { + public static CompletableFuture suggest(Stream stream, SuggestionsBuilder builder) { + return suggest(stream.toList(), x -> x, builder); + } + + public static CompletableFuture suggest(Iterable iterable, SuggestionsBuilder builder) { + return suggest(iterable, x -> x, builder); + } + + public static CompletableFuture suggest(Iterable iterable, Function map, SuggestionsBuilder builder) { + String remaining = builder.getRemainingLowerCase(); + for (T t : iterable) { + String target = map.apply(t).toLowerCase(Locale.ROOT); + if (target.equals(remaining)) { + builder.suggest(target); + return builder.buildFuture(); + } + } + + for (T t : iterable) { + String target = map.apply(t).toLowerCase(Locale.ROOT); + if (target.contains(remaining)) builder.suggest(target); + } + + return builder.buildFuture(); + } +} diff --git a/src/main/java/me/alpha432/oyvey/features/commands/Command.java b/src/main/java/me/alpha432/oyvey/features/commands/Command.java index 2e271a5..c654be1 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/Command.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/Command.java @@ -6,10 +6,12 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import me.alpha432.oyvey.features.Feature; import me.alpha432.oyvey.manager.CommandManager; import me.alpha432.oyvey.util.TextUtil; -import me.alpha432.oyvey.util.player.ChatUtil; +import me.alpha432.oyvey.util.chat.ChatUtil; +import me.alpha432.oyvey.util.chat.Signature; import static com.mojang.brigadier.Command.SINGLE_SUCCESS; -import static me.alpha432.oyvey.features.commands.MessageIdentifiers.*; +import static me.alpha432.oyvey.features.commands.MessageSignatures.FAIL; +import static me.alpha432.oyvey.features.commands.MessageSignatures.SUCCESS; public abstract class Command extends Feature { public static final int NO_OP = -1; @@ -59,12 +61,12 @@ public abstract class Command extends Feature { return true; } - public static void sendMessage(String message, String identifier) { + public static void sendMessage(String message, Signature identifier) { if (message == null) return; ChatUtil.sendMessage(TextUtil.text(message), identifier); } - public static void sendMessage(String message, String identifier, Object... format) { + public static void sendMessage(String message, Signature identifier, Object... format) { if (message == null) return; ChatUtil.sendMessage(TextUtil.text(message, format), identifier); } diff --git a/src/main/java/me/alpha432/oyvey/features/commands/MessageIdentifiers.java b/src/main/java/me/alpha432/oyvey/features/commands/MessageIdentifiers.java deleted file mode 100644 index 0e072e4..0000000 --- a/src/main/java/me/alpha432/oyvey/features/commands/MessageIdentifiers.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.alpha432.oyvey.features.commands; - -public class MessageIdentifiers { - public static final String GENERAL = "general"; - public static final String SUCCESS = "success"; - public static final String FAIL = "fail"; -} \ No newline at end of file diff --git a/src/main/java/me/alpha432/oyvey/features/commands/MessageSignatures.java b/src/main/java/me/alpha432/oyvey/features/commands/MessageSignatures.java new file mode 100644 index 0000000..ca8782a --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/features/commands/MessageSignatures.java @@ -0,0 +1,10 @@ +package me.alpha432.oyvey.features.commands; + +import me.alpha432.oyvey.util.chat.Signature; +import me.alpha432.oyvey.util.chat.SimpleSignature; + +public class MessageSignatures { + public static final Signature GENERAL = SimpleSignature.fromLong(-1L); + public static final Signature SUCCESS = SimpleSignature.fromLong(0L); + public static final Signature FAIL = SimpleSignature.fromLong(1L); +} \ No newline at end of file diff --git a/src/main/java/me/alpha432/oyvey/features/commands/ModuleCommand.java b/src/main/java/me/alpha432/oyvey/features/commands/ModuleCommand.java index 7cf59c2..1960918 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/ModuleCommand.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/ModuleCommand.java @@ -2,10 +2,16 @@ package me.alpha432.oyvey.features.commands; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import me.alpha432.oyvey.OyVey; import me.alpha432.oyvey.features.commands.argument.ColorArgumentType; import me.alpha432.oyvey.features.modules.Module; import me.alpha432.oyvey.features.settings.Setting; import me.alpha432.oyvey.manager.CommandManager; +import me.alpha432.oyvey.util.chat.ChatUtil; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.Style; import java.awt.*; @@ -29,6 +35,7 @@ public class ModuleCommand extends Command { @SuppressWarnings("unchecked") @Override public void createArgumentBuilder(LiteralArgumentBuilder builder) { + registerDefault(builder); for (Setting setting : module.getSettings()) { Class type = setting.getDefaultValue().getClass(); @@ -46,6 +53,29 @@ public class ModuleCommand extends Command { } } + private void registerDefault(LiteralArgumentBuilder builder) { + builder.executes(ctx -> { + var message = Component.empty(); + + message.append("[ "); + message.append(Component.literal(module.getName()) + .withStyle(s -> s.withColor(module.isToggled() ? ChatFormatting.GREEN : ChatFormatting.RED)) + .withStyle(s -> s.withClickEvent(suggestCommand("toggle " + module.getName()))) + ); + message.append(" ]"); + + for (Setting setting : module.getSettings()) { + message.append("\n"); + message.append(Component.literal(setting.getName() + ": ").withStyle(ChatFormatting.GRAY)); + message.append(Component.literal(setting.getValueAsString()).withStyle(s -> styledValue(setting, s))); + } + + ChatUtil.sendMessage(message, MessageSignatures.SUCCESS); + + return success(); + }); + } + private void registerColorArgument(LiteralArgumentBuilder builder, Setting setting) { builder.then(literal(setting.getName().toLowerCase()) @@ -110,6 +140,19 @@ public class ModuleCommand extends Command { return success("Set %s.%s to %s", module.getName(), setting.getName(), setting.getValue()); } + private static ClickEvent suggestCommand(String command) { + return new ClickEvent.SuggestCommand(OyVey.commandManager.getCommandPrefix() + command); + } + + private static Style styledValue(Setting setting, Style style) { + return switch (setting.getValue()) { + case Boolean value -> style.withColor(value ? ChatFormatting.GREEN : ChatFormatting.RED); + case Color value -> style.withColor(value.getRGB()); + case Enum ignored -> style.withColor(ChatFormatting.YELLOW); + default -> style.withColor(ChatFormatting.WHITE); + }; + } + @Override public boolean isShown() { return false; diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/ColorArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/ColorArgumentType.java index c1c7be2..e4ebe92 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/argument/ColorArgumentType.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/ColorArgumentType.java @@ -4,13 +4,20 @@ 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 me.alpha432.oyvey.features.commands.CommandExceptions; +import net.minecraft.ChatFormatting; import java.awt.*; +import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.concurrent.CompletableFuture; -public class ColorArgumentType implements ArgumentType { +import static me.alpha432.oyvey.features.commands.ArgumentSuggestions.suggest; + +public final class ColorArgumentType implements ArgumentType { private static final List EXAMPLES = List.of("hsb:55,100,100", "255,0,255", "0,255,255,80"); private static final String[] RGBA_VALUES = {"Red", "Green", "Blue", "Alpha"}; @@ -21,7 +28,16 @@ public class ColorArgumentType implements ArgumentType { // if input begins with "#" its a hex color if (value.startsWith("#")) { - return new Color(Integer.parseInt(value.substring(1), 16)); + int color; + if (value.length() == 4) { + char[] c = value.toCharArray(); + String hex = "" + c[1] + c[1] + c[2] + c[2] + c[3] + c[3]; + color = Integer.parseInt(hex, 16); + } else { + color = Integer.parseInt(value.substring(1), 16); + } + + return new Color(color); } if (value.startsWith("hsb:")) { @@ -50,6 +66,11 @@ public class ColorArgumentType implements ArgumentType { (float) brightness / 100.0f); } + ChatFormatting format = parseFormatting(value); + if (format != null) { + return new Color(format.getColor(), false); + } + int[] elements = parseColorElements(reader, value); for (int i = 0; i < elements.length; ++i) { int element = elements[i]; @@ -65,6 +86,29 @@ public class ColorArgumentType implements ArgumentType { elements.length == 4 ? elements[3] : 255); } + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + String input = builder.getRemainingLowerCase(); + if (input.isEmpty()) { + builder.suggest("#"); + builder.suggest("hsb:"); + return builder.buildFuture(); + } + + if (input.startsWith("#")) { + builder.suggest(input); + } else if (input.startsWith("h")) { + if (input.startsWith("hsb:")) builder.suggest(input); + else builder.suggest("hsb:"); + } else if (!Character.isDigit(input.charAt(0))){ + return suggest(Arrays.stream(ChatFormatting.values()) + .filter(ChatFormatting::isColor) + .map(ChatFormatting::getName), builder); + } + + return builder.buildFuture(); + } + private int[] parseColorElements(StringReader reader, String value) throws CommandSyntaxException { String[] parts = value.split(","); if (parts.length < 3) { @@ -79,6 +123,16 @@ public class ColorArgumentType implements ArgumentType { return elements; } + private ChatFormatting parseFormatting(String value) { + for (ChatFormatting format : ChatFormatting.values()) { + if (!format.isColor()) continue; + if (value.equalsIgnoreCase(format.getName())) { + return format; + } + } + return null; + } + @Override public Collection getExamples() { return EXAMPLES; diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/CommandArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/CommandArgumentType.java index 02e266c..bb358e8 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/argument/CommandArgumentType.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/CommandArgumentType.java @@ -13,7 +13,9 @@ import me.alpha432.oyvey.features.commands.CommandExceptions; import java.util.concurrent.CompletableFuture; -public class CommandArgumentType implements ArgumentType, CommandExceptionType { +import static me.alpha432.oyvey.features.commands.ArgumentSuggestions.suggest; + +public final class CommandArgumentType implements ArgumentType, CommandExceptionType { @Override public Command parse(StringReader reader) throws CommandSyntaxException { String value = reader.readString().toLowerCase(); @@ -29,16 +31,7 @@ public class CommandArgumentType implements ArgumentType, CommandExcept @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - String input = builder.getRemainingLowerCase(); - - for (String alias : OyVey.commandManager.getCommandAliases()) { - String name = alias.toLowerCase(); - if (name.contains(input)) { - builder.suggest(name); - } - } - - return builder.buildFuture(); + return suggest(OyVey.commandManager.getCommandAliases(), builder); } public static Command getCommand(CommandContext ctx, String name) { diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/EnumArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/EnumArgumentType.java index b0e3d64..663a167 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/argument/EnumArgumentType.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/EnumArgumentType.java @@ -12,7 +12,9 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; -public class EnumArgumentType> implements ArgumentType { +import static me.alpha432.oyvey.features.commands.ArgumentSuggestions.suggest; + +public final class EnumArgumentType> implements ArgumentType { private final Map enumNameMap = new HashMap<>(); private final T defaultValue; @@ -42,14 +44,7 @@ public class EnumArgumentType> implements ArgumentType { @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - String input = builder.getRemainingLowerCase(); - for (String key : enumNameMap.keySet()) { - String name = key.toLowerCase(); - if (name.contains(input)) { - builder.suggest(name); - } - } - return builder.buildFuture(); + return suggest(enumNameMap.keySet(), builder); } @SuppressWarnings("unchecked") diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/GreedyArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/GreedyArgumentType.java new file mode 100644 index 0000000..b0a4366 --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/GreedyArgumentType.java @@ -0,0 +1,40 @@ +package me.alpha432.oyvey.features.commands.argument; + +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 java.lang.reflect.Array; +import java.util.concurrent.CompletableFuture; + +public record GreedyArgumentType(ArgumentType parent, Class type) implements ArgumentType { + @Override + @SuppressWarnings("unchecked") + public T[] parse(StringReader reader) throws CommandSyntaxException { + String input = reader.getRemaining(); + reader.setCursor(reader.getTotalLength()); + String[] split = input.split(" "); + T[] values = (T[]) Array.newInstance(type, split.length); + for (int i = 0; i < split.length; i++) { + values[i] = parent.parse(new StringReader(split[i])); + } + return values; + } + + @Override public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + String[] s = builder.getRemaining().split(" ", -1); + if (s.length == 0) { + return parent.listSuggestions(context, builder); + } + + int st = builder.getStart() + builder.getRemaining().length() - s[s.length - 1].length(); + return parent.listSuggestions(context, new SuggestionsBuilder(builder.getInput(), st)); + } + + public static GreedyArgumentType greedy(ArgumentType parent, Class type) { + return new GreedyArgumentType<>(parent, type); + } +} diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/KeybindArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/KeybindArgumentType.java new file mode 100644 index 0000000..96f41e4 --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/KeybindArgumentType.java @@ -0,0 +1,45 @@ +package me.alpha432.oyvey.features.commands.argument; + +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 me.alpha432.oyvey.features.commands.CommandExceptions; +import me.alpha432.oyvey.features.settings.Bind; +import me.alpha432.oyvey.util.KeyboardUtil; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import static me.alpha432.oyvey.features.commands.ArgumentSuggestions.suggest; + +public final class KeybindArgumentType implements ArgumentType { + private static final List EXAMPLES = List.of("A", "RIGHT_SHIFT", "MOUSE0"); + + @Override + public Bind parse(StringReader reader) throws CommandSyntaxException { + String input = reader.readString(); + Bind bind = KeyboardUtil.getBind(input); + if (bind == null) { + throw CommandExceptions.invalidArgument("Invalid key name").createWithContext(reader); + } + return bind; + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return suggest(KeyboardUtil.iterateKeys(), builder); + } + + @Override + public Collection getExamples() { + return EXAMPLES; + } + + public static KeybindArgumentType keybind() { + return new KeybindArgumentType(); + } +} diff --git a/src/main/java/me/alpha432/oyvey/features/commands/argument/ModuleArgumentType.java b/src/main/java/me/alpha432/oyvey/features/commands/argument/ModuleArgumentType.java index 02ba08a..0135ce2 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/argument/ModuleArgumentType.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/argument/ModuleArgumentType.java @@ -7,11 +7,14 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import me.alpha432.oyvey.OyVey; +import me.alpha432.oyvey.features.Feature; import me.alpha432.oyvey.features.commands.CommandExceptions; import me.alpha432.oyvey.features.modules.Module; import java.util.concurrent.CompletableFuture; +import static me.alpha432.oyvey.features.commands.ArgumentSuggestions.suggest; + public record ModuleArgumentType(boolean fullName) implements ArgumentType { @Override public Module parse(StringReader reader) throws CommandSyntaxException { @@ -28,17 +31,7 @@ public record ModuleArgumentType(boolean fullName) implements ArgumentType CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - String input = builder.getRemainingLowerCase(); - - for (Module module : OyVey.moduleManager.getModules()) { - String name = module.getName().toLowerCase(); - String displayName = module.getDisplayName().toLowerCase(); - if (name.contains(input) || displayName.contains(input)) { - builder.suggest(name); - } - } - - return builder.buildFuture(); + return suggest(OyVey.moduleManager.getModules(), Feature::getName, builder); } public static ModuleArgumentType module() { diff --git a/src/main/java/me/alpha432/oyvey/features/commands/impl/BindCommand.java b/src/main/java/me/alpha432/oyvey/features/commands/impl/BindCommand.java index aa5fe73..8294664 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/impl/BindCommand.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/impl/BindCommand.java @@ -9,7 +9,7 @@ import me.alpha432.oyvey.features.settings.Bind; import me.alpha432.oyvey.manager.CommandManager; import me.alpha432.oyvey.util.KeyboardUtil; -import static me.alpha432.oyvey.features.commands.argument.ModuleArgumentType.getModule; +import static me.alpha432.oyvey.features.commands.argument.KeybindArgumentType.keybind; import static me.alpha432.oyvey.features.commands.argument.ModuleArgumentType.module; import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE; import static org.lwjgl.glfw.GLFW.GLFW_KEY_UNKNOWN; @@ -25,11 +25,20 @@ public class BindCommand extends Command { @Override public void createArgumentBuilder(LiteralArgumentBuilder builder) { - builder.then(argument("module", module(true)) - .executes((ctx) -> { - module = getModule(ctx, "module"); - return success("Press any key..."); - })); + builder.then(argument("module", module(true)).then( + argument("keybind", keybind()).executes(ctx -> { + Module module = ctx.getArgument("module", Module.class); + Bind bind = ctx.getArgument("keybind", Bind.class); + module.bind.setValue(bind); + return success("Bind for {green} %s {} set to {green} %s", + module.getName(), + KeyboardUtil.getKeyName(bind) + ); + }) + ).executes((ctx) -> { + module = ctx.getArgument("module", Module.class); + return success("Press any key..."); + })); } @Subscribe @@ -40,14 +49,16 @@ public class BindCommand extends Command { if (event.getKey() == GLFW_KEY_ESCAPE) { module = null; - sendMessage("Operation canceled.", "fail"); + fail("Operation canceled."); return; } - sendMessage("Bind for {green} %s {} set to {green} %s", + module.bind.setValue(Bind.keyboard(event.getKey())); + success("Bind for {green} %s {} set to {green} %s", module.getName(), - KeyboardUtil.getKeyName(event.getKey())); - module.bind.setValue(new Bind(event.getKey())); + KeyboardUtil.getKeyName(module.getBind()) + ); + module = null; } } diff --git a/src/main/java/me/alpha432/oyvey/features/commands/impl/HelpCommand.java b/src/main/java/me/alpha432/oyvey/features/commands/impl/HelpCommand.java index 42376f9..7354e35 100644 --- a/src/main/java/me/alpha432/oyvey/features/commands/impl/HelpCommand.java +++ b/src/main/java/me/alpha432/oyvey/features/commands/impl/HelpCommand.java @@ -5,17 +5,27 @@ import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.CommandNode; +import me.alpha432.oyvey.OyVey; import me.alpha432.oyvey.features.commands.Command; import me.alpha432.oyvey.manager.CommandManager; +import me.alpha432.oyvey.util.chat.ChatUtil; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.network.chat.MutableComponent; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.StringJoiner; +import static me.alpha432.oyvey.features.commands.MessageSignatures.GENERAL; import static me.alpha432.oyvey.features.commands.argument.CommandArgumentType.command; import static me.alpha432.oyvey.features.commands.argument.CommandArgumentType.getCommand; import static me.alpha432.oyvey.features.commands.argument.NumberArgumentType.get; import static me.alpha432.oyvey.features.commands.argument.NumberArgumentType.number; +import static me.alpha432.oyvey.util.TextUtil.text; +import static me.alpha432.oyvey.util.chat.ChatUtil.prefix; +import static me.alpha432.oyvey.util.chat.ChatUtil.withPrefix; public class HelpCommand extends Command { private static final int ITEMS_PER_PAGE = 5; @@ -28,28 +38,36 @@ public class HelpCommand extends Command { @Override public void createArgumentBuilder(LiteralArgumentBuilder builder) { builder.then(argument("page", number(Integer.class)) - .executes((ctx) -> helpCommands(ctx, get(Integer.class, ctx, "page"))) + .executes((ctx) -> helpCommands(ctx, get(Integer.class, ctx, "page")))) .then(argument("command_name", command()) .executes(this::helpSpecific)) - .executes((ctx) -> helpCommands(ctx, 1))); + .executes((ctx) -> helpCommands(ctx, 1)); } private int helpSpecific(CommandContext ctx) { Command command = getCommand(ctx, "command_name"); - sendMessage("Usages for %s:", command.getName()); + + MutableComponent text = Component.empty(); + text.append(withPrefix("Usages for %s:\n", command.getName())); ParseResults results = ctx.getSource().getDispatcher() .parse(command.getName(), ctx.getSource()); + if (results.getContext().getNodes().isEmpty()) { - return success("No usages available"); - } + text.append(withPrefix("No usages available")); + } else { + Map, String> smartUsages = ctx.getSource().getDispatcher().getSmartUsage( + Iterables.getLast(results.getContext().getNodes()).getNode(), ctx.getSource()); + List usages = new ArrayList<>(); - Map, String> smartUsages = ctx.getSource().getDispatcher().getSmartUsage( - Iterables.getLast(results.getContext().getNodes()).getNode(), ctx.getSource()); - for (String usage : smartUsages.values()) { - sendMessage(".%s %s", results.getReader().getString(), usage); + for (String usage : smartUsages.values()) { + usages.add(text(" {gray}.%s %s", command.getName(), usage)); + } + + text.append(ComponentUtils.formatList(usages, Component.literal("\n"))); } + ChatUtil.sendClientSideMessage(text, GENERAL); return success(); } @@ -66,18 +84,38 @@ public class HelpCommand extends Command { List paginated = commands.subList((pageIndex - 1) * ITEMS_PER_PAGE, Math.min(commands.size(), pageIndex * ITEMS_PER_PAGE)); - sendMessage("Commands (%s):", "general", commands.size()); + MutableComponent text = Component.empty(); + text.append(withPrefix("Commands (%s): \n", commands.size())); for (Command command : paginated) { - StringJoiner joiner = new StringJoiner(", "); - for (String alias : command.getAliases()) { - joiner.add(alias); - } - - sendMessage("{dark_gray} %s: {reset}\n %s", "general", - joiner, command.getDescription()); + String aliases = String.join(", ", command.getAliases()); + String description = command.getDescription(); + text.append(withPrefix("{dark_gray} %s: {reset}\n %s\n", aliases, description)); } - return success("Page %s/%s", pageIndex, pages); + text.append(buildPages(pageIndex, pages)); + + ChatUtil.sendClientSideMessage(text, GENERAL); + return success(); + } + + private static Component buildPages(int index, int pages) { + String command = OyVey.commandManager.getCommandPrefix() + "help "; + MutableComponent text = prefix(); + boolean hasPages = pages > 1; + + if (hasPages && index != 1) + text.append(suggest(Component.literal(" <"), command + (index - 1))); + + text.append(text(" Page %d/%d", index, pages)); + + if (hasPages && index != pages) + text.append(suggest(Component.literal(" > "), command + (index + 1))); + + return text; + } + + private static Component suggest(MutableComponent component, String command) { + return component.withStyle(s -> s.withClickEvent(new ClickEvent.SuggestCommand(command.formatted()))); } } diff --git a/src/main/java/me/alpha432/oyvey/features/gui/items/buttons/BindButton.java b/src/main/java/me/alpha432/oyvey/features/gui/items/buttons/BindButton.java index 7d0b116..e3dd078 100644 --- a/src/main/java/me/alpha432/oyvey/features/gui/items/buttons/BindButton.java +++ b/src/main/java/me/alpha432/oyvey/features/gui/items/buttons/BindButton.java @@ -5,6 +5,7 @@ import me.alpha432.oyvey.features.gui.OyVeyGui; import me.alpha432.oyvey.features.modules.client.ClickGuiModule; import me.alpha432.oyvey.features.settings.Bind; import me.alpha432.oyvey.features.settings.Setting; +import me.alpha432.oyvey.util.KeyboardUtil; import me.alpha432.oyvey.util.render.RenderUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; @@ -30,8 +31,7 @@ public class BindButton if (this.isListening) { drawString("Press a Key...", this.x + 2.3f, this.y - 1.7f - (float) OyVeyGui.getClickGui().getTextOffset(), -1); } else { - String str = this.setting.getValue().toString().toUpperCase(); - str = str.replace("KEY.KEYBOARD", "").replace(".", " "); + String str = KeyboardUtil.getKeyName(setting.getValue()); drawString(this.setting.getName() + " " + ChatFormatting.GRAY + str, this.x + 2.3f, this.y - 1.7f - (float) OyVeyGui.getClickGui().getTextOffset(), this.getState() ? -1 : -5592406); } } diff --git a/src/main/java/me/alpha432/oyvey/features/modules/Module.java b/src/main/java/me/alpha432/oyvey/features/modules/Module.java index 86c5942..c2cc663 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/Module.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/Module.java @@ -8,6 +8,7 @@ import me.alpha432.oyvey.event.impl.render.Render2DEvent; import me.alpha432.oyvey.event.impl.render.Render3DEvent; import me.alpha432.oyvey.features.Feature; import me.alpha432.oyvey.features.commands.Command; +import me.alpha432.oyvey.features.commands.MessageSignatures; import me.alpha432.oyvey.features.settings.Bind; import me.alpha432.oyvey.features.settings.Setting; import me.alpha432.oyvey.manager.ConfigManager; @@ -88,11 +89,13 @@ public class Module extends Feature implements Jsonable, Toggleable { Module module = OyVey.moduleManager.getModuleByDisplayName(name); Module originalModule = OyVey.moduleManager.getModuleByName(name); if (module == null && originalModule == null) { - Command.sendMessage(this.getDisplayName() + ", name: " + this.getName() + ", has been renamed to: " + name, "general"); + Command.sendMessage("%, name: %s, has been renamed to: %s", MessageSignatures.GENERAL, + getDisplayName(), getName(), name); this.displayName.setValue(name); return; } - Command.sendMessage("{red} A module of this name already exists.", "general"); + + Command.sendMessage("{red} A module of this name already exists.", MessageSignatures.GENERAL); } @Override diff --git a/src/main/java/me/alpha432/oyvey/features/modules/client/ClickGuiModule.java b/src/main/java/me/alpha432/oyvey/features/modules/client/ClickGuiModule.java index 81a2c75..d065657 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/client/ClickGuiModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/client/ClickGuiModule.java @@ -11,16 +11,18 @@ import org.lwjgl.glfw.GLFW; import java.awt.*; +import static me.alpha432.oyvey.features.commands.MessageSignatures.GENERAL; + public class ClickGuiModule extends Module { private static ClickGuiModule INSTANCE; - public Setting prefix = str("Prefix", "."); - public Setting color = color("Color", 0, 0, 255, 180); - public Setting topColor = color("TopColor", 0, 0, 150, 240); - public Setting rainbow = bool("Rainbow", false); - public Setting rainbowHue = num("Delay", 240, 0, 600); - public Setting rainbowBrightness = num("Brightness", 150.0f, 1.0f, 255.0f); - public Setting rainbowSaturation = num("Saturation", 150.0f, 1.0f, 255.0f); + public final Setting prefix = str("Prefix", "."); + public final Setting color = color("Color", 0, 0, 255, 180); + public final Setting topColor = color("TopColor", 0, 0, 150, 240); + public final Setting rainbow = bool("Rainbow", false); + public final Setting rainbowHue = num("Delay", 240, 0, 600); + public final Setting rainbowBrightness = num("Brightness", 150.0f, 1.0f, 255.0f); + public final Setting rainbowSaturation = num("Saturation", 150.0f, 1.0f, 255.0f); public ClickGuiModule() { super("ClickGui", "Opens the ClickGui", Module.Category.CLIENT); @@ -36,7 +38,7 @@ public class ClickGuiModule extends Module { if (event.getType() == ClientEvent.Type.SETTING_UPDATE && event.getSetting().getFeature().equals(this)) { if (event.getSetting().equals(this.prefix)) { OyVey.commandManager.setCommandPrefix(this.prefix.getPlannedValue()); - Command.sendMessage("Prefix set to {global} %s", OyVey.commandManager.getCommandPrefix()); + Command.sendMessage("Prefix set to {global} %s", GENERAL, OyVey.commandManager.getCommandPrefix()); } if (event.getSetting().equals(this.color)) { OyVey.colorManager.setColor(this.color.getPlannedValue()); diff --git a/src/main/java/me/alpha432/oyvey/features/modules/client/NotificationsModule.java b/src/main/java/me/alpha432/oyvey/features/modules/client/NotificationsModule.java index cda421a..46c2955 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/client/NotificationsModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/client/NotificationsModule.java @@ -5,12 +5,14 @@ import me.alpha432.oyvey.event.system.Subscribe; import me.alpha432.oyvey.features.modules.Module; import me.alpha432.oyvey.features.settings.Setting; import me.alpha432.oyvey.util.TextUtil; -import me.alpha432.oyvey.util.player.ChatUtil; +import me.alpha432.oyvey.util.chat.ChatUtil; + +import static me.alpha432.oyvey.util.chat.SimpleSignature.from; public class NotificationsModule extends Module { - private static final String MODULE_FORMAT = "Toggled %s %s %s"; + private static final String MODULE_FORMAT = "{gray} %s %s%s"; - public Setting moduleToggle = bool("Module Toggle", true); + public final Setting moduleToggle = bool("ModuleToggle", true); public NotificationsModule() { super("Notifications", "Displays notifications for various client events", Category.CLIENT); @@ -28,6 +30,6 @@ public class NotificationsModule extends Module { ChatUtil.sendMessage(TextUtil.text(MODULE_FORMAT, event.getFeature().getName(), moduleState ? "{green}" : "{red}", - moduleState ? "on" : "off"), event.getFeature().getName()); + moduleState ? "on" : "off"), from(event.getFeature().getName())); } } diff --git a/src/main/java/me/alpha432/oyvey/features/modules/hud/CoordinatesHudModule.java b/src/main/java/me/alpha432/oyvey/features/modules/hud/CoordinatesHudModule.java index ec1a096..715d317 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/hud/CoordinatesHudModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/hud/CoordinatesHudModule.java @@ -5,7 +5,7 @@ import me.alpha432.oyvey.features.modules.client.HudModule; import me.alpha432.oyvey.features.settings.Setting; public class CoordinatesHudModule extends HudModule { - public Setting nether = bool("Nether", false); + public final Setting nether = bool("Nether", false); public CoordinatesHudModule() { super("Coordinates", "Display coordinates", 150, 20); diff --git a/src/main/java/me/alpha432/oyvey/features/modules/hud/WatermarkHudModule.java b/src/main/java/me/alpha432/oyvey/features/modules/hud/WatermarkHudModule.java index d4ce55e..708996c 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/hud/WatermarkHudModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/hud/WatermarkHudModule.java @@ -7,8 +7,8 @@ import me.alpha432.oyvey.util.BuildConfig; import me.alpha432.oyvey.util.TextUtil; public class WatermarkHudModule extends HudModule { - public Setting text = str("Text", BuildConfig.NAME); - public Setting fullVersion = new Setting<>("FullVersion", false); + public final Setting text = str("Text", BuildConfig.NAME); + public final Setting fullVersion = new Setting<>("FullVersion", false); public WatermarkHudModule() { super("Watermark", "Display watermark", 100, 10); diff --git a/src/main/java/me/alpha432/oyvey/features/modules/misc/MCFModule.java b/src/main/java/me/alpha432/oyvey/features/modules/misc/MCFModule.java index b7f4b8e..4d3d012 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/misc/MCFModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/misc/MCFModule.java @@ -7,6 +7,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import org.lwjgl.glfw.GLFW; +import static me.alpha432.oyvey.util.chat.SimpleSignature.from; + public class MCFModule extends Module { private boolean pressed; @@ -32,10 +34,10 @@ public class MCFModule extends Module { if (OyVey.friendManager.isFriend(name)) { OyVey.friendManager.removeFriend(name); - Command.sendMessage("{red} %s has been unfriended.", name); + Command.sendMessage("{red} %s has been unfriended.", from(getName()), name); } else { OyVey.friendManager.addFriend(name); - Command.sendMessage("{aqua} %s has been friended.", name); + Command.sendMessage("{aqua} %s has been friended.", from(getName()), name); } } } diff --git a/src/main/java/me/alpha432/oyvey/features/modules/player/NoFallModule.java b/src/main/java/me/alpha432/oyvey/features/modules/player/NoFallModule.java index a5e6cd3..889bfc7 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/player/NoFallModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/player/NoFallModule.java @@ -13,9 +13,9 @@ public class NoFallModule extends Module { public void onTick() { if (!mc.player.onGround() && OyVey.positionManager.getFallDistance() > 3) { boolean bl = mc.player.horizontalCollision; - ServerboundMovePlayerPacket.PosRot pakcet = new ServerboundMovePlayerPacket.PosRot(mc.player.getX(), mc.player.getY() + 0.000000001, mc.player.getZ(), + ServerboundMovePlayerPacket.PosRot packet = new ServerboundMovePlayerPacket.PosRot(mc.player.getX(), mc.player.getY() + 0.000000001, mc.player.getZ(), mc.player.getYRot(), mc.player.getXRot(), false, bl); - mc.player.connection.send(pakcet); + mc.player.connection.send(packet); } } } diff --git a/src/main/java/me/alpha432/oyvey/features/modules/render/BlockHighlightModule.java b/src/main/java/me/alpha432/oyvey/features/modules/render/BlockHighlightModule.java index 643b09e..474a303 100644 --- a/src/main/java/me/alpha432/oyvey/features/modules/render/BlockHighlightModule.java +++ b/src/main/java/me/alpha432/oyvey/features/modules/render/BlockHighlightModule.java @@ -14,8 +14,8 @@ import net.minecraft.world.phys.shapes.VoxelShape; import java.awt.*; public class BlockHighlightModule extends Module { - public Setting color = color("Color", 255, 0, 0, 255); - public Setting lineWidth = num("LineWidth", 1.0f, 0.1f, 5.0f); + public final Setting color = color("Color", 255, 0, 0, 255); + public final Setting lineWidth = num("LineWidth", 1.0f, 0.1f, 5.0f); public BlockHighlightModule() { super("BlockHighlight", "Draws box at the block that you are looking at", Category.RENDER); @@ -26,9 +26,9 @@ public class BlockHighlightModule extends Module { if (mc.hitResult instanceof BlockHitResult result) { VoxelShape shape = mc.level.getBlockState(result.getBlockPos()).getShape(mc.level, result.getBlockPos()); if (shape.isEmpty() || result.getType() == HitResult.Type.MISS) return; - AABB box = shape.bounds(); - box = box.move(result.getBlockPos()); - RenderUtil.drawBox(event.getMatrix(), box, color.getValue(), lineWidth.getValue()); + AABB aabb = shape.bounds(); + aabb = aabb.move(result.getBlockPos()); + RenderUtil.drawBox(event.getMatrix(), aabb, color.getValue(), lineWidth.getValue()); } } diff --git a/src/main/java/me/alpha432/oyvey/features/settings/Bind.java b/src/main/java/me/alpha432/oyvey/features/settings/Bind.java index 05d2825..c8ed2ed 100644 --- a/src/main/java/me/alpha432/oyvey/features/settings/Bind.java +++ b/src/main/java/me/alpha432/oyvey/features/settings/Bind.java @@ -15,6 +15,14 @@ public class Bind implements Util { this.key = key; } + public static Bind keyboard(int key) { + return new Bind(key); + } + + public static Bind mouse(int key) { + return new Bind(-key - 2); + } + public static Bind none() { return new Bind(-1); } @@ -31,10 +39,14 @@ public class Bind implements Util { return this.key == -1; } + public boolean isMouse() { + return key < -1; + } + public String toString() { if (this.isEmpty()) return "None"; if (this.key < -1) return "Mouse " + (-this.key - 1); - return this.capitalise(InputConstants.getKey(new KeyEvent(this.key, 0, 0)).getName()); + return this.capitalise(InputConstants.getKey(new KeyEvent(this.key, 0, 0)).getName().replace("key.keyboard.", "")); } public boolean isDown() { @@ -67,7 +79,7 @@ public class Bind implements Util { } int key = -1; try { - key = InputConstants.getKey(s.toUpperCase()).getValue(); + key = InputConstants.getKey("key.keyboard" + s).getValue(); } catch (Exception e) { } if (key == 0) return Bind.none(); diff --git a/src/main/java/me/alpha432/oyvey/features/settings/Setting.java b/src/main/java/me/alpha432/oyvey/features/settings/Setting.java index 4df00fe..7577015 100644 --- a/src/main/java/me/alpha432/oyvey/features/settings/Setting.java +++ b/src/main/java/me/alpha432/oyvey/features/settings/Setting.java @@ -4,6 +4,7 @@ import me.alpha432.oyvey.event.impl.ClientEvent; import me.alpha432.oyvey.features.Feature; import org.joml.Vector2f; +import java.awt.*; import java.util.Objects; import java.util.function.Predicate; @@ -255,6 +256,9 @@ public class Setting { } public String getValueAsString() { + if (value instanceof Color color) { + return "%d, %d, %d".formatted(color.getRed(), color.getGreen(), color.getBlue()); + } return this.value.toString(); } diff --git a/src/main/java/me/alpha432/oyvey/manager/CommandManager.java b/src/main/java/me/alpha432/oyvey/manager/CommandManager.java index a1906b1..d9394af 100644 --- a/src/main/java/me/alpha432/oyvey/manager/CommandManager.java +++ b/src/main/java/me/alpha432/oyvey/manager/CommandManager.java @@ -15,9 +15,9 @@ import org.apache.logging.log4j.Logger; import java.util.*; -import static com.mojang.brigadier.Command.SINGLE_SUCCESS; import static me.alpha432.oyvey.features.commands.Command.SINGLE_FAILURE; -import static me.alpha432.oyvey.features.commands.MessageIdentifiers.GENERAL; +import static me.alpha432.oyvey.features.commands.MessageSignatures.GENERAL; +import static me.alpha432.oyvey.features.commands.MessageSignatures.SUCCESS; public class CommandManager extends Feature implements Jsonable { private static final Logger LOGGER = LogManager.getLogger("Commands"); @@ -48,10 +48,8 @@ public class CommandManager extends Feature implements Jsonable { try { int result = dispatcher.execute(message.substring(commandPrefix.length()).trim(), this); - if (result == SINGLE_SUCCESS) { - Command.sendMessage("{green} Command executed successfully", GENERAL); - } else if (result == SINGLE_FAILURE) { - Command.sendMessage("{red} Failed to execute command", GENERAL); + if (result == SINGLE_FAILURE) { + Command.sendMessage("{red} Failed to execute command", SUCCESS); } } catch (CommandSyntaxException e) { LOGGER.error("Failed to execute command", e); diff --git a/src/main/java/me/alpha432/oyvey/mixin/render/MixinChatComponent.java b/src/main/java/me/alpha432/oyvey/mixin/render/MixinChatComponent.java index 5b29f7e..5e1fcb8 100644 --- a/src/main/java/me/alpha432/oyvey/mixin/render/MixinChatComponent.java +++ b/src/main/java/me/alpha432/oyvey/mixin/render/MixinChatComponent.java @@ -4,7 +4,6 @@ import me.alpha432.oyvey.ducks.render.IChatComponent; import net.minecraft.client.GuiMessage; import net.minecraft.client.gui.components.ChatComponent; import net.minecraft.network.chat.MessageSignature; - import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/me/alpha432/oyvey/util/KeyboardUtil.java b/src/main/java/me/alpha432/oyvey/util/KeyboardUtil.java index 3669a64..c0afbf8 100644 --- a/src/main/java/me/alpha432/oyvey/util/KeyboardUtil.java +++ b/src/main/java/me/alpha432/oyvey/util/KeyboardUtil.java @@ -1,11 +1,57 @@ package me.alpha432.oyvey.util; +import com.mojang.blaze3d.platform.InputConstants; import me.alpha432.oyvey.features.settings.Bind; +import net.minecraft.client.input.KeyEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; public class KeyboardUtil { - public static String getKeyName(int key) { - String str = new Bind(key).toString().toUpperCase(); - str = str.replace("KEY.KEYBOARD", "").replace(".", " "); - return str; + public static String getKeyName(int key, boolean mouse) { + return getKeyName(mouse ? Bind.mouse(key) : Bind.keyboard(key)); + } + + public static String getKeyName(Bind bind) { + if (bind.isEmpty()) return "NONE"; + if (bind.isMouse()) return "MOUSE" + (-bind.getKey() - 1); + return getKeyName(InputConstants.getKey(new KeyEvent(bind.getKey(), 0, 0))); + } + + public static String getKeyName(InputConstants.Key key) { + return key.getName() + .replace("key.mouse.", "") + .replace("key.keyboard.", "") + .replace(".", "_") + .toUpperCase(Locale.ROOT); + } + + public static Bind getBind(String name) { + String lowercaseName = name.toLowerCase(Locale.ROOT).replace("_", "."); + if (name.startsWith("mouse")) { + try { + return new Bind(-Integer.parseInt(name.substring(5)) - 1); + } catch (Exception e) { + return null; + } + } + + try { + InputConstants.Key key = InputConstants.getKey("key.keyboard." + lowercaseName); + return new Bind(key.getValue()); + } catch (IllegalArgumentException exception) { + return null; + } + } + + public static Iterable iterateKeys() { + List keys = new ArrayList<>(); + for (InputConstants.Key key : InputConstants.Type.KEYSYM.map.values()) + keys.add(getKeyName(key)); + for (int i = 1; i <= 9; i++) { + keys.add("MOUSE" + i); + } + return keys; } } diff --git a/src/main/java/me/alpha432/oyvey/util/player/ChatUtil.java b/src/main/java/me/alpha432/oyvey/util/chat/ChatUtil.java similarity index 54% rename from src/main/java/me/alpha432/oyvey/util/player/ChatUtil.java rename to src/main/java/me/alpha432/oyvey/util/chat/ChatUtil.java index 01964f8..3ee3730 100644 --- a/src/main/java/me/alpha432/oyvey/util/player/ChatUtil.java +++ b/src/main/java/me/alpha432/oyvey/util/chat/ChatUtil.java @@ -1,35 +1,51 @@ -package me.alpha432.oyvey.util.player; +package me.alpha432.oyvey.util.chat; import me.alpha432.oyvey.OyVey; import me.alpha432.oyvey.ducks.render.IChatComponent; import me.alpha432.oyvey.features.commands.Command; +import me.alpha432.oyvey.util.TextUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.GuiMessage; import net.minecraft.client.GuiMessageTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MessageSignature; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; -import java.nio.charset.StandardCharsets; - import static me.alpha432.oyvey.util.traits.Util.mc; public class ChatUtil { - public static void sendMessage(Component message, String identifier) { - sendClientSideMessage(Component.empty() - .setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY)) - .append("<") - .append(getClientNameComponent()) - .append(">") - .append(" ") - .append(message), identifier); + public static MutableComponent prefix() { + return withPrefix((Component) null); } - public static void sendClientSideMessage(Component message, String identifier) { + public static MutableComponent withPrefix(String string) { + return withPrefix(string, new Object[0]); + } + + public static MutableComponent withPrefix(String string, Object... o) { + return withPrefix(TextUtil.text(string, o)); + } + + public static MutableComponent withPrefix(Component component) { + MutableComponent text = Component.empty() + .setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY)) + .append(Component.literal("<")) + .append(getClientNameComponent()) + .append(Component.literal(">")); + if (component != null) text.append(" ").append(component); + return text; + } + + public static void sendMessage(Component message, Signature identifier) { + sendClientSideMessage(withPrefix(message), identifier); + } + + public static void sendClientSideMessage(Component message, Signature sig) { if (Command.nullCheck()) return; IChatComponent chat = (IChatComponent) mc.gui.getChat(); - MessageSignature signature = new MessageSignature(get256Bytes(identifier)); + MessageSignature signature = new MessageSignature(sig.getByteSignature()); chat.oyvey$removeMessage(signature); chat.oyvey$addMessage(new GuiMessage(mc.gui.getGuiTicks(), message, signature, getMessageTag())); } @@ -41,11 +57,4 @@ public class ChatUtil { private static GuiMessageTag getMessageTag() { return new GuiMessageTag(OyVey.colorManager.getColorAsInt(), null, null, null); } - - private static byte[] get256Bytes(String identifier) { - byte[] bytes = new byte[256]; - byte[] identifierBytes = identifier.getBytes(StandardCharsets.UTF_8); - System.arraycopy(identifierBytes, 0, bytes, 0, Math.min(bytes.length, identifierBytes.length)); - return bytes; - } } \ No newline at end of file diff --git a/src/main/java/me/alpha432/oyvey/util/chat/Signature.java b/src/main/java/me/alpha432/oyvey/util/chat/Signature.java new file mode 100644 index 0000000..3cf50d2 --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/util/chat/Signature.java @@ -0,0 +1,5 @@ +package me.alpha432.oyvey.util.chat; + +public interface Signature { + byte[] getByteSignature(); +} diff --git a/src/main/java/me/alpha432/oyvey/util/chat/SimpleSignature.java b/src/main/java/me/alpha432/oyvey/util/chat/SimpleSignature.java new file mode 100644 index 0000000..da2b671 --- /dev/null +++ b/src/main/java/me/alpha432/oyvey/util/chat/SimpleSignature.java @@ -0,0 +1,61 @@ +package me.alpha432.oyvey.util.chat; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class SimpleSignature implements Signature { + private static final MessageDigest MESSAGE_DIGEST; + + private final byte[] signature; + + SimpleSignature(byte[] signature) { + this.signature = signature; + } + + public static SimpleSignature from(String content) { + byte[] sig = allocateBuf() + .put((byte) 1) + .put(sha256(content)) + .array(); + return new SimpleSignature(sig); + } + + public static SimpleSignature fromInt(int id) { + byte[] sig = allocateBuf() + .put((byte) 2) + .putInt(id) + .array(); + return new SimpleSignature(sig); + } + + public static SimpleSignature fromLong(long id) { + byte[] sig = allocateBuf() + .put((byte) 3) + .putLong(id) + .array(); + return new SimpleSignature(sig); + } + + @Override + public byte[] getByteSignature() { + return signature; + } + + private static byte[] sha256(String content) { + return MESSAGE_DIGEST.digest(content.getBytes(StandardCharsets.UTF_8)); + } + + private static ByteBuffer allocateBuf() { + return ByteBuffer.allocate(256); + } + + static { + try { + MESSAGE_DIGEST = MessageDigest.getInstance("SHA-512"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/resources/oyvey.accesswidener b/src/main/resources/oyvey.accesswidener index a60449a..e7c0586 100644 --- a/src/main/resources/oyvey.accesswidener +++ b/src/main/resources/oyvey.accesswidener @@ -5,4 +5,5 @@ accessible field net/minecraft/network/protocol/game/ServerboundInteractPacket e accessible method net/minecraft/network/protocol/game/ServerboundInteractPacket$Action getType ()Lnet/minecraft/network/protocol/game/ServerboundInteractPacket$ActionType; accessible class net/minecraft/network/protocol/game/ServerboundInteractPacket$ActionType accessible field net/minecraft/network/protocol/game/ServerboundInteractPacket action Lnet/minecraft/network/protocol/game/ServerboundInteractPacket$Action; -accessible method net/minecraft/client/multiplayer/MultiPlayerGameMode ensureHasSentCarriedItem ()V \ No newline at end of file +accessible method net/minecraft/client/multiplayer/MultiPlayerGameMode ensureHasSentCarriedItem ()V +accessible field com/mojang/blaze3d/platform/InputConstants$Type map Lit/unimi/dsi/fastutil/ints/Int2ObjectMap; \ No newline at end of file