diff --git a/src/main/java/land/chipmunk/chipmunkmod/commands/SayCommand.java b/src/main/java/land/chipmunk/chipmunkmod/commands/SayCommand.java index d7dd797..61c0f9b 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/commands/SayCommand.java +++ b/src/main/java/land/chipmunk/chipmunkmod/commands/SayCommand.java @@ -3,6 +3,7 @@ package land.chipmunk.chipmunkmod.commands; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; +import land.chipmunk.chipmunkmod.modules.Chat; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import static com.mojang.brigadier.arguments.StringArgumentType.getString; @@ -11,8 +12,6 @@ import static land.chipmunk.chipmunkmod.command.CommandManager.argument; import static land.chipmunk.chipmunkmod.command.CommandManager.literal; public class SayCommand { - public static boolean saying = false; - public static void register (CommandDispatcher dispatcher) { dispatcher.register( literal("say") @@ -24,13 +23,7 @@ public class SayCommand { } public static int say (CommandContext context) { - saying = true; - - final FabricClientCommandSource source = context.getSource(); - - source.getClient().getNetworkHandler().sendChatMessage(getString(context, "message")); - - saying = false; + Chat.sendChatMessage(getString(context, "message"), true); return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java index 412298b..02f7694 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ChatScreenMixin.java @@ -1,5 +1,10 @@ package land.chipmunk.chipmunkmod.mixin; +import com.google.gson.JsonObject; +import land.chipmunk.chipmunkmod.ChipmunkMod; +import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; +import land.chipmunk.chipmunkmod.modules.ChomeNSBotCommandSuggestions; +import land.chipmunk.chipmunkmod.util.BotValidationUtilities; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ChatInputSuggestor; import net.minecraft.client.gui.screen.Screen; @@ -14,6 +19,12 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import javax.net.ssl.HttpsURLConnection; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.util.List; + @Mixin(value = net.minecraft.client.gui.screen.ChatScreen.class) public class ChatScreenMixin extends Screen { @Shadow protected TextFieldWidget chatField; @@ -57,6 +68,53 @@ public class ChatScreenMixin extends Screen { client.inGameHud.getChatHud().addToMessageHistory(chatText); } + if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null && chatText.startsWith(ChipmunkMod.CONFIG.bots.testbot.prefix)) { + ChipmunkMod.executorService.submit(() -> { + try { + final URL url = new URL(ChipmunkMod.CONFIG.bots.testbot.webhookUrl); + + final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.addRequestProperty("Content-Type", "application/json"); + connection.addRequestProperty("User-Agent", "ChipmunkMod"); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + + final JsonObject jsonObject = new JsonObject(); + + jsonObject.addProperty("username", "ChipmunkMod UwU"); + jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername()); + + final OutputStream stream = connection.getOutputStream(); + stream.write(jsonObject.toString().getBytes()); + stream.flush(); + stream.close(); + + connection.getInputStream().close(); + connection.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) { + final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands; + + final List moreOrTrustedCommands = commands.stream() + .filter((command) -> command.trustLevel != ChomeNSBotCommand.TrustLevel.PUBLIC) + .map((command) -> command.name.toLowerCase()) + .toList(); + + if (moreOrTrustedCommands.contains(chatText.toLowerCase().split("\\s")[0])) { + try { + BotValidationUtilities.chomens(chatText.substring(ChipmunkMod.CONFIG.bots.chomens.prefix.length())); + + cir.setReturnValue(true); + cir.cancel(); + + return; + } catch (Exception ignored) {} + } + } + if (chatText.startsWith("/")) { client.player.networkHandler.sendChatCommand(chatText.substring(1)); } else { diff --git a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java index efbef93..1da9e9f 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/land/chipmunk/chipmunkmod/mixin/ClientPlayNetworkHandlerMixin.java @@ -1,15 +1,11 @@ package land.chipmunk.chipmunkmod.mixin; -import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.command.CommandManager; -import land.chipmunk.chipmunkmod.commands.SayCommand; -import land.chipmunk.chipmunkmod.data.ChomeNSBotCommand; import land.chipmunk.chipmunkmod.listeners.Listener; import land.chipmunk.chipmunkmod.listeners.ListenerManager; import land.chipmunk.chipmunkmod.modules.*; -import land.chipmunk.chipmunkmod.util.BotValidationUtilities; import net.kyori.adventure.text.TextComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; @@ -18,6 +14,13 @@ import net.minecraft.client.network.ServerInfo; import net.minecraft.client.util.telemetry.WorldSession; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.network.ClientConnection; +import net.minecraft.network.encryption.NetworkEncryptionUtils; +import net.minecraft.network.message.LastSeenMessagesCollector; +import net.minecraft.network.message.MessageBody; +import net.minecraft.network.message.MessageChain; +import net.minecraft.network.message.MessageSignatureData; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket; import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerRemoveS2CPacket; @@ -31,16 +34,17 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import javax.net.ssl.HttpsURLConnection; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URL; -import java.util.List; +import java.time.Instant; @Mixin(value = net.minecraft.client.network.ClientPlayNetworkHandler.class, priority = 1001) public class ClientPlayNetworkHandlerMixin { @Shadow private FeatureSet enabledFeatures; @Shadow private CombinedDynamicRegistries combinedDynamicRegistries; + @Shadow private LastSeenMessagesCollector lastSeenMessagesCollector; + @Shadow private MessageChain.Packer messagePacker; + + @Shadow + public void sendPacket(Packet packet) {} @Inject(method = "", at = @At("TAIL")) private void init (MinecraftClient client, Screen screen, ClientConnection connection, ServerInfo serverInfo, GameProfile profile, WorldSession worldSession, CallbackInfo ci) { @@ -102,63 +106,31 @@ public class ClientPlayNetworkHandlerMixin { } @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) - private void injectedSendChatMessage (String chatText, CallbackInfo ci) { + private void sendChatMessage (String chatText, CallbackInfo ci) { final CommandManager commandManager = CommandManager.INSTANCE; - if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null && chatText.startsWith(ChipmunkMod.CONFIG.bots.testbot.prefix)) { - ChipmunkMod.executorService.submit(() -> { - try { - final URL url = new URL(ChipmunkMod.CONFIG.bots.testbot.webhookUrl); - - final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - connection.addRequestProperty("Content-Type", "application/json"); - connection.addRequestProperty("User-Agent", "ChipmunkMod"); - connection.setDoOutput(true); - connection.setRequestMethod("POST"); - - final JsonObject jsonObject = new JsonObject(); - - jsonObject.addProperty("username", "ChipmunkMod UwU"); - jsonObject.addProperty("content", MinecraftClient.getInstance().getSession().getUsername()); - - final OutputStream stream = connection.getOutputStream(); - stream.write(jsonObject.toString().getBytes()); - stream.flush(); - stream.close(); - - connection.getInputStream().close(); - connection.disconnect(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } else if (chatText.startsWith(ChipmunkMod.CONFIG.bots.chomens.prefix)) { - final List commands = ChomeNSBotCommandSuggestions.INSTANCE.commands; - - final List moreOrTrustedCommands = commands.stream() - .filter((command) -> command.trustLevel != ChomeNSBotCommand.TrustLevel.PUBLIC) - .map((command) -> command.name.toLowerCase()) - .toList(); - - if (moreOrTrustedCommands.contains(chatText.toLowerCase().split("\\s")[0])) { - try { - BotValidationUtilities.chomens(chatText.substring(ChipmunkMod.CONFIG.bots.chomens.prefix.length())); - - ci.cancel(); - - return; - } catch (Exception ignored) {} - } - } + final String secret = String.valueOf(Chat.secret); if (chatText.startsWith(commandManager.prefix)) { commandManager.executeCommand(chatText.substring(commandManager.prefix.length())); ci.cancel(); - } else if (!chatText.startsWith("/") && !SayCommand.saying) { + } else if (!chatText.startsWith("/") && !chatText.startsWith(secret)) { CustomChat.INSTANCE.chat(chatText); ci.cancel(); } + + if (chatText.startsWith(secret)) { + final String content = chatText.substring(secret.length()); + + Instant instant = Instant.now(); + long l = NetworkEncryptionUtils.SecureRandomUtil.nextLong(); + LastSeenMessagesCollector.LastSeenMessages lastSeenMessages = this.lastSeenMessagesCollector.collect(); + MessageSignatureData messageSignatureData = this.messagePacker.pack(new MessageBody(content, instant, l, lastSeenMessages.lastSeen())); + this.sendPacket(new ChatMessageC2SPacket(content, instant, l, messageSignatureData, lastSeenMessages.update())); + + ci.cancel(); + } } } diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/Chat.java b/src/main/java/land/chipmunk/chipmunkmod/modules/Chat.java new file mode 100644 index 0000000..2f56502 --- /dev/null +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/Chat.java @@ -0,0 +1,18 @@ +package land.chipmunk.chipmunkmod.modules; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; + +public class Chat { + public static double secret = Math.random(); + + public static void sendChatMessage (String message) { sendChatMessage(message, false); } + public static void sendChatMessage (String message, boolean usePlayerChat) { + if (message == null) return; + + final ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); + + if (usePlayerChat) networkHandler.sendChatMessage(secret + message); + else networkHandler.sendChatMessage(message); + } +} diff --git a/src/main/java/land/chipmunk/chipmunkmod/modules/CustomChat.java b/src/main/java/land/chipmunk/chipmunkmod/modules/CustomChat.java index 0e8cdad..6a59ae8 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/modules/CustomChat.java +++ b/src/main/java/land/chipmunk/chipmunkmod/modules/CustomChat.java @@ -56,10 +56,7 @@ public class CustomChat { } if (!enabled || !player.hasPermissionLevel(2) || !player.isCreative()) { - final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); - SayCommand.saying = true; - networkHandler.sendChatMessage(message); - SayCommand.saying = false; + Chat.sendChatMessage(message, true); return; } diff --git a/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java b/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java index 5292378..12d304f 100644 --- a/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java +++ b/src/main/java/land/chipmunk/chipmunkmod/util/BotValidationUtilities.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.Command; import land.chipmunk.chipmunkmod.ChipmunkMod; import land.chipmunk.chipmunkmod.Configuration; import land.chipmunk.chipmunkmod.commands.SayCommand; +import land.chipmunk.chipmunkmod.modules.Chat; import land.chipmunk.chipmunkmod.modules.CustomChat; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; @@ -33,9 +34,7 @@ public class BotValidationUtilities { BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); String stringHash = bigInt.toString(Character.MAX_RADIX); - SayCommand.saying = true; - networkHandler.sendChatMessage(prefix + command + " " + stringHash); - SayCommand.saying = false; + Chat.sendChatMessage(prefix + command + " " + stringHash, true); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } @@ -60,9 +59,7 @@ public class BotValidationUtilities { BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); String stringHash = bigInt.toString(Character.MAX_RADIX); - SayCommand.saying = true; - networkHandler.sendChatMessage(prefix + command + " " + stringHash); - SayCommand.saying = false; + Chat.sendChatMessage(prefix + command + " " + stringHash, true); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } @@ -110,7 +107,7 @@ public class BotValidationUtilities { " " + String.join(" ", restArguments); - CustomChat.INSTANCE.chat(toSend); + Chat.sendChatMessage(toSend); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } @@ -134,9 +131,7 @@ public class BotValidationUtilities { BigInteger bigInt = new BigInteger(1, Arrays.copyOfRange(hash, 0, 4)); String stringHash = bigInt.toString(Character.MAX_RADIX); - SayCommand.saying = true; - networkHandler.sendChatMessage(prefix + command + " " + stringHash); - SayCommand.saying = false; + Chat.sendChatMessage(prefix + command + " " + stringHash, true); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }