diff --git a/changelog.md b/changelog.md index b4342e2..06a0317 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,4 @@ - Add activation ratelimiter - Add reversal key for cycling macros - Add placeholder for targeted block +- Prevent sending messages when placeholders fail diff --git a/common/src/main/java/dev/terminalmc/commandkeys/CommandKeys.java b/common/src/main/java/dev/terminalmc/commandkeys/CommandKeys.java index 8cc5422..64e0eb1 100644 --- a/common/src/main/java/dev/terminalmc/commandkeys/CommandKeys.java +++ b/common/src/main/java/dev/terminalmc/commandkeys/CommandKeys.java @@ -17,6 +17,7 @@ package dev.terminalmc.commandkeys; import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.datafixers.util.Pair; import dev.terminalmc.commandkeys.config.Config; import dev.terminalmc.commandkeys.config.Macro; import dev.terminalmc.commandkeys.config.Profile; @@ -30,6 +31,7 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import java.util.ArrayList; import java.util.List; @@ -119,22 +121,40 @@ public static boolean canTrigger(InputConstants.Key key) { } public static void send(String message, boolean addToHistory, boolean showHudMsg) { + send(false, message, addToHistory, showHudMsg); + } + + public static void type(String message) { + send(true, message, false, false); + } + + public static void send(boolean type, String message, boolean addToHistory, boolean showHudMsg) { Minecraft mc = Minecraft.getInstance(); if (mc.player == null) return; - message = PlaceholderUtil.replace(message); - // new ChatScreen("").handleChatInput(message, addToHistory) - // could be slightly better for compat but costs performance. - if (message.startsWith("/")) { - mc.player.connection.sendCommand(message.substring(1)); + Pair result = PlaceholderUtil.replace(message); + message = result.getFirst(); + int faults = result.getSecond(); + if (faults == 0) { + if (type) { + mc.setScreen(new ChatScreen(message)); + } else { + // new ChatScreen("").handleChatInput(message, addToHistory) + // could be slightly better for compat but costs performance. + if (message.startsWith("/")) { + mc.player.connection.sendCommand(message.substring(1)); + } else { + mc.player.connection.sendChat(message); + } + if (addToHistory) mc.gui.getChat().addRecentChat(message); + if (showHudMsg) mc.gui.setOverlayMessage(Component.literal(message) + .withStyle(ChatFormatting.GRAY), false); + } } else { - mc.player.connection.sendChat(message); + MutableComponent msg = PREFIX.copy(); + msg.append(localized("message", "placeholderFault", + Component.literal(message).withStyle(ChatFormatting.GRAY)) + .withStyle(ChatFormatting.RED)); + mc.gui.getChat().addMessage(msg); } - if (addToHistory) mc.gui.getChat().addRecentChat(message); - if (showHudMsg) mc.gui.setOverlayMessage(Component.literal(message) - .withStyle(ChatFormatting.GRAY), false); - } - - public static void type(String message) { - Minecraft.getInstance().setScreen(new ChatScreen(PlaceholderUtil.replace(message))); } } diff --git a/common/src/main/java/dev/terminalmc/commandkeys/util/PlaceholderUtil.java b/common/src/main/java/dev/terminalmc/commandkeys/util/PlaceholderUtil.java index f0cbc6b..1010683 100644 --- a/common/src/main/java/dev/terminalmc/commandkeys/util/PlaceholderUtil.java +++ b/common/src/main/java/dev/terminalmc/commandkeys/util/PlaceholderUtil.java @@ -16,6 +16,7 @@ package dev.terminalmc.commandkeys.util; +import com.mojang.datafixers.util.Pair; import dev.terminalmc.commandkeys.CommandKeys; import dev.terminalmc.commandkeys.mixin.accessor.ChatComponentAccessor; import net.minecraft.client.GuiMessage; @@ -40,9 +41,7 @@ public class PlaceholderUtil { - // Entity.pick for blocks - // ProjectileUtil.getEntityHitResult for entities - + private static int faults; private static @Nullable BlockPos playerBlockPos; private static @Nullable BlockPos lookBlockPos; private static @Nullable Vec3 lookAngle; @@ -81,21 +80,27 @@ public class PlaceholderUtil { * Breaks if player is not in-game. Does not self-check for performance * reasons, but expects caller to validate. */ - public static String replace(String message) { - if (!message.contains("%")) return message; - clearCache(); + public static Pair replace(String message) { + if (!message.contains("%")) return new Pair<>(message, 0); + reset(); for (SimplePlaceholder p : SIMPLE_PLACEHOLDERS) message = p.process(message); for (Placeholder p : REGEX_PLACEHOLDERS) message = p.process(message); - return message; + return new Pair<>(message, faults); } - private static void clearCache() { + private static void reset() { + faults = 0; playerBlockPos = null; lookBlockPos = null; lookAngle = null; pmSenderName = null; } + + private static String fault() { + faults++; + return "?"; + } private record SimplePlaceholder(String string, Supplier supplier) { public String process(String message) { @@ -134,7 +139,7 @@ private static String getRecentChat(@NotNull String[] pattern) { return matcher.group(1); } catch (IndexOutOfBoundsException e) { CommandKeys.LOG.error("Recent chat placeholder failed: Group 1 not available: " + e); - return "?"; + return fault(); } } } @@ -144,7 +149,7 @@ private static String getRecentChat(@NotNull String[] pattern) { CommandKeys.LOG.error("Recent chat placeholder failed: Invalid regex: " + e); } - return "?"; + return fault(); } // Clipboard @@ -153,17 +158,17 @@ private static String getClipboard(@Nullable String[] pattern) { String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard(); if (clipboard.isEmpty()) { CommandKeys.LOG.warn("Clipboard placeholder failed: No data"); - return "?"; + return fault(); } if (pattern != null) { try { if (!Pattern.compile(pattern[0]).matcher(clipboard).find()) { CommandKeys.LOG.warn("Clipboard placeholder failed: Non-matching regex"); - return "?"; + return fault(); } } catch (PatternSyntaxException e) { CommandKeys.LOG.warn("Clipboard placeholder failed: Invalid regex: " + e); - return "?"; + return fault(); } } return clipboard; @@ -173,7 +178,7 @@ private static String getClipboard(@Nullable String[] pattern) { private static String getLastMessage() { String lastMsg = Minecraft.getInstance().gui.getChat().getRecentChat().peekLast(); - if (lastMsg == null) return "?"; + if (lastMsg == null) return fault(); return lastMsg; } @@ -184,7 +189,7 @@ private static String getLastCommand() { } else { CommandKeys.LOG.error("Command history not ArrayListDeque"); } - return "?"; + return fault(); } // Player name @@ -210,7 +215,7 @@ private static String getPmSenderName() { } if (pmSenderName == null) { CommandKeys.LOG.warn("PmSenderName placeholder failed: No message found: Checked " + i); - return "?"; + return fault(); } return pmSenderName; } @@ -224,6 +229,7 @@ private static BlockPos updatePlayerBlockPos() { } private static BlockPos updateLookBlockPos() { + // Note: ProjectileUtil.getEntityHitResult for entities if (lookBlockPos == null) { Minecraft mc = Minecraft.getInstance(); // Distance is arbitrary but will do for now @@ -243,7 +249,7 @@ private static Vec3 updateLookAngle() { } private static String getPlayerBlockPos(String[] args) { - if (updatePlayerBlockPos() == null || updateLookAngle() == null) return "? ? ?"; + if (updatePlayerBlockPos() == null || updateLookAngle() == null) return fault(); int offset = Integer.parseInt(args[1]); Vec3 playerPos = playerBlockPos.getBottomCenter(); if (offset != 0) playerPos = offsetCardinalDirection( @@ -253,22 +259,22 @@ private static String getPlayerBlockPos(String[] args) { } private static String getPlayerBlockX(String[] offset) { - if (updatePlayerBlockPos() == null) return "?"; + if (updatePlayerBlockPos() == null) return fault(); return String.valueOf(Mth.floor(playerBlockPos.getX()) + Integer.parseInt(offset[0])); } private static String getPlayerBlockY(String[] offset) { - if (updatePlayerBlockPos() == null) return "?"; + if (updatePlayerBlockPos() == null) return fault(); return String.valueOf(Mth.floor(playerBlockPos.getY()) + Integer.parseInt(offset[0])); } private static String getPlayerBlockZ(String[] offset) { - if (updatePlayerBlockPos() == null) return "?"; + if (updatePlayerBlockPos() == null) return fault(); return String.valueOf(Mth.floor(playerBlockPos.getZ()) + Integer.parseInt(offset[0])); } private static String getLookBlockPos(String[] args) { - if (updateLookBlockPos() == null || updateLookAngle() == null) return "? ? ?"; + if (updateLookBlockPos() == null || updateLookAngle() == null) return fault(); int offset = Integer.parseInt(args[1]); Vec3 playerPos = lookBlockPos.getBottomCenter(); if (offset != 0) playerPos = offsetCardinalDirection( @@ -278,17 +284,17 @@ private static String getLookBlockPos(String[] args) { } private static String getLookBlockX(String[] offset) { - if (updateLookBlockPos() == null) return "?"; + if (updateLookBlockPos() == null) return fault(); return String.valueOf(Mth.floor(lookBlockPos.getX()) + Integer.parseInt(offset[0])); } private static String getLookBlockY(String[] offset) { - if (updateLookBlockPos() == null) return "?"; + if (updateLookBlockPos() == null) return fault(); return String.valueOf(Mth.floor(lookBlockPos.getY()) + Integer.parseInt(offset[0])); } private static String getLookBlockZ(String[] offset) { - if (updateLookBlockPos() == null) return "?"; + if (updateLookBlockPos() == null) return fault(); return String.valueOf(Mth.floor(lookBlockPos.getZ()) + Integer.parseInt(offset[0])); } diff --git a/common/src/main/resources/assets/commandkeys/lang/de_de.json b/common/src/main/resources/assets/commandkeys/lang/de_de.json index 3868155..9d68283 100644 --- a/common/src/main/resources/assets/commandkeys/lang/de_de.json +++ b/common/src/main/resources/assets/commandkeys/lang/de_de.json @@ -1,6 +1,7 @@ { "key.commandkeys.main": "CommandKeys", "key.commandkeys.main.edit": "Aktives Profil bearbeiten", + "message.commandkeys.placeholderFault": "Message \"%s\" could not be sent because one or more placeholders failed to apply.", "message.commandkeys.sendBlocked": "Ratelimit exceeded by key %s. Ratelimit is set to %s activations in %s ticks.", "option.commandkeys.key": "Makro Optionen", "option.commandkeys.key.alt.tooltip": "This key, if pressed when the macro is activated, will reverse the cycle order.", diff --git a/common/src/main/resources/assets/commandkeys/lang/en_us.json b/common/src/main/resources/assets/commandkeys/lang/en_us.json index 4762650..0a3c3a5 100644 --- a/common/src/main/resources/assets/commandkeys/lang/en_us.json +++ b/common/src/main/resources/assets/commandkeys/lang/en_us.json @@ -1,6 +1,7 @@ { "key.commandkeys.main": "CommandKeys", "key.commandkeys.main.edit": "Edit Active Profile", + "message.commandkeys.placeholderFault": "Message \"%s\" could not be sent because one or more placeholders failed to apply.", "message.commandkeys.sendBlocked": "Ratelimit exceeded by key %s. Ratelimit is set to %s activations in %s ticks.", "option.commandkeys.key": "Macro Options", "option.commandkeys.key.alt.tooltip": "This key, if pressed when the macro is activated, will reverse the cycle order.", diff --git a/common/src/main/resources/assets/commandkeys/lang/zh_cn.json b/common/src/main/resources/assets/commandkeys/lang/zh_cn.json index 08ca936..a0dca3a 100644 --- a/common/src/main/resources/assets/commandkeys/lang/zh_cn.json +++ b/common/src/main/resources/assets/commandkeys/lang/zh_cn.json @@ -1,6 +1,7 @@ { "key.commandkeys.main": "命令按键(CommandKeys)", "key.commandkeys.main.edit": "编辑活动配置文件", + "message.commandkeys.placeholderFault": "Message \"%s\" could not be sent because one or more placeholders failed to apply.", "message.commandkeys.sendBlocked": "Ratelimit exceeded by key %s. Ratelimit is set to %s activations in %s ticks.", "option.commandkeys.key": "宏选项", "option.commandkeys.key.alt.tooltip": "This key, if pressed when the macro is activated, will reverse the cycle order.",