From 061371f40bfff848d085798cbf238749169e7cc7 Mon Sep 17 00:00:00 2001 From: ChomeNS <95471003+ChomeNS@users.noreply.github.com> Date: Sat, 19 Apr 2025 15:34:38 +0700 Subject: [PATCH] refactor: move all information things for chomens mod into the encrypted payload and some improvements --- build-number.txt | 2 +- .../java/me/chayapak1/chomens_bot/Bot.java | 2 +- .../plugins/ChomeNSModIntegrationPlugin.java | 136 +++++++++--------- 3 files changed, 67 insertions(+), 73 deletions(-) diff --git a/build-number.txt b/build-number.txt index 51680442..0ef1ac49 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -2874 \ No newline at end of file +2881 \ No newline at end of file diff --git a/src/main/java/me/chayapak1/chomens_bot/Bot.java b/src/main/java/me/chayapak1/chomens_bot/Bot.java index f9cb9a30..36f76bdb 100644 --- a/src/main/java/me/chayapak1/chomens_bot/Bot.java +++ b/src/main/java/me/chayapak1/chomens_bot/Bot.java @@ -135,13 +135,13 @@ public class Bot extends SessionAdapter { this.chat = new ChatPlugin(this); this.commandSpy = new CommandSpyPlugin(this); this.query = new QueryPlugin(this); + this.extrasMessenger = new ExtrasMessengerPlugin(this); this.chomeNSMod = new ChomeNSModIntegrationPlugin(this); this.commandSuggestion = new CommandSuggestionPlugin(this); this.logger = new LoggerPlugin(this); this.position = new PositionPlugin(this); this.serverFeatures = new ServerFeaturesPlugin(this); this.selfCare = new SelfCarePlugin(this); - this.extrasMessenger = new ExtrasMessengerPlugin(this); this.world = new WorldPlugin(this); this.core = new CorePlugin(this); this.team = new TeamPlugin(this); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java index 7de2b1e7..58b6bcc3 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java @@ -1,13 +1,12 @@ package me.chayapak1.chomens_bot.plugins; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.chomeNSMod.Encryptor; import me.chayapak1.chomens_bot.chomeNSMod.Packet; import me.chayapak1.chomens_bot.chomeNSMod.PacketHandler; +import me.chayapak1.chomens_bot.chomeNSMod.Types; import me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets.ClientboundHandshakePacket; import me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets.ServerboundRunCommandPacket; import me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets.ServerboundRunCoreCommandPacket; @@ -18,7 +17,6 @@ import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.data.player.PlayerEntry; import me.chayapak1.chomens_bot.util.Ascii85; -import me.chayapak1.chomens_bot.util.UUIDUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; @@ -33,8 +31,7 @@ import java.util.concurrent.ConcurrentHashMap; public class ChomeNSModIntegrationPlugin implements Listener { private static final String ID = "chomens_mod"; - private static final int ASCII85_CHUNK_SIZE = 31_000; // just 32767 trimmed "a bit" - private static final int EXTRAS_CHUNK_SIZE = 32_500; // just 32767 trimmed a bit + private static final int CHUNK_SIZE = 31_000 / 2; // some Magical Number private static final long NONCE_EXPIRATION_MS = 30 * 1000; // 30 seconds @@ -54,7 +51,7 @@ public class ChomeNSModIntegrationPlugin implements Listener { public final List connectedPlayers = Collections.synchronizedList(new ArrayList<>()); - private final Map> receivedParts = new ConcurrentHashMap<>(); + private final Map> receivedParts = new ConcurrentHashMap<>(); private final List seenMetadata = Collections.synchronizedList(new ArrayList<>()); @@ -85,74 +82,73 @@ public class ChomeNSModIntegrationPlugin implements Listener { metadata.serialize(buf); buf.writeInt(packet.getId()); + packet.serialize(buf); - final byte[] bytes = new byte[buf.readableBytes()]; - buf.readBytes(bytes); + final byte[] rawBytes = new byte[buf.readableBytes()]; + buf.readBytes(rawBytes); try { final int messageId = RANDOM.nextInt(); - final byte[] encrypted = Encryptor.encrypt(bytes, bot.config.chomeNSMod.password); + final List chunks = new ArrayList<>(); + + for (int i = 0; i < rawBytes.length; i += CHUNK_SIZE) { + final int end = Math.min(rawBytes.length, i + CHUNK_SIZE); + final byte[] chunk = Arrays.copyOfRange(rawBytes, i, end); + chunks.add(chunk); + } + + if (chunks.size() > 512) { + bot.logger.error( + Component.translatable( + "Chunk is too large (%s) while trying to send packet %s to %s!", + Component.text(chunks.size()), + Component.text(packet.toString()), + Component.text(target.profile.getIdAsString()) + ) + ); + return; + } // FIXME: not sure how to implement on the mod side yet final boolean supportsExtrasMessaging = false; // bot.extrasMessenger.isSupported; - if (supportsExtrasMessaging) { - // TODO: test this - // TODO: implement receiver - final List chunks = new ArrayList<>(); + int i = 1; - for (int i = 0; i < encrypted.length; i += EXTRAS_CHUNK_SIZE) { - final int end = Math.min(encrypted.length, i + EXTRAS_CHUNK_SIZE); - final byte[] chunk = Arrays.copyOfRange(encrypted, i, end); - chunks.add(chunk); - } + for (final byte[] chunk : chunks) { + final PayloadState state = i == chunks.size() + ? PayloadState.DONE + : PayloadState.JOINING; - int i = 1; + final ByteBuf toSendBuf = Unpooled.buffer(); - for (final byte[] chunk : chunks) { - final PayloadState state = i == chunks.size() - ? PayloadState.DONE - : PayloadState.JOINING; + toSendBuf.writeInt(messageId); + toSendBuf.writeShort(state.ordinal()); // short or byte? + toSendBuf.writeBytes(chunk); - final ByteBuf extrasBuf = Unpooled.buffer(); + final byte[] toSendBytes = new byte[toSendBuf.readableBytes()]; + toSendBuf.readBytes(toSendBytes); - extrasBuf.writeInt(messageId); - extrasBuf.writeShort(state.ordinal()); // short or byte? - extrasBuf.writeBytes(chunk); + final byte[] encrypted = Encryptor.encrypt(toSendBytes, bot.config.chomeNSMod.password); - final byte[] extrasBytes = new byte[buf.readableBytes()]; - extrasBuf.readBytes(extrasBytes); - - bot.extrasMessenger.sendPayload(ID, extrasBytes); - - i++; - } - } else { - final String encryptedAscii85 = Ascii85.encode(encrypted); - - final Iterable chunks = Splitter.fixedLength(ASCII85_CHUNK_SIZE).split(encryptedAscii85); - - int i = 1; - - for (final String chunk : chunks) { - final PayloadState state = i == Iterables.size(chunks) - ? PayloadState.DONE - : PayloadState.JOINING; + if (supportsExtrasMessaging) { + // TODO: test this + // TODO: implement receiver + bot.extrasMessenger.sendPayload(ID, encrypted); + } else { + final String ascii85EncryptedPayload = Ascii85.encode(encrypted); final Component component = Component.translatable( "", Component.text(ID), - Component.text(messageId), - Component.text(state.ordinal()), - Component.text(chunk) + Component.text(ascii85EncryptedPayload) ); bot.chat.actionBar(component, target.profile.getId()); - - i++; } + + i++; } } catch (final Exception ignored) { } } @@ -220,54 +216,52 @@ public class ChomeNSModIntegrationPlugin implements Listener { final List arguments = translatableComponent.arguments(); if ( - arguments.size() != 5 || + arguments.size() != 2 || !(arguments.get(0).asComponent() instanceof final TextComponent idTextComponent) || - !(arguments.get(1).asComponent() instanceof final TextComponent uuidTextComponent) || - !(arguments.get(2).asComponent() instanceof final TextComponent messageIdTextComponent) || - !(arguments.get(3).asComponent() instanceof final TextComponent payloadStateTextComponent) || - !(arguments.get(4).asComponent() instanceof final TextComponent payloadTextComponent) || + !(arguments.get(1).asComponent() instanceof final TextComponent payloadTextComponent) || !idTextComponent.content().equals(ID) ) return true; try { - final UUID uuid = UUIDUtilities.tryParse(uuidTextComponent.content()); + final byte[] decrypted = Encryptor.decrypt( + Ascii85.decode(payloadTextComponent.content()), + bot.config.chomeNSMod.password + ); - if (uuid == null) return true; + final ByteBuf chunkBuf = Unpooled.wrappedBuffer(decrypted); + + final UUID uuid = Types.readUUID(chunkBuf); final PlayerEntry player = bot.players.getEntry(uuid); if (player == null) return false; - final int messageId = Integer.parseInt(messageIdTextComponent.content()); - final int payloadStateIndex = Integer.parseInt(payloadStateTextComponent.content()); + final int messageId = chunkBuf.readInt(); + final short payloadStateIndex = chunkBuf.readShort(); final PayloadState payloadState = PayloadState.values()[payloadStateIndex]; receivedParts.putIfAbsent(player, new ConcurrentHashMap<>()); - final Map playerReceivedParts = receivedParts.get(player); + final Map playerReceivedParts = receivedParts.get(player); - if (!playerReceivedParts.containsKey(messageId)) playerReceivedParts.put(messageId, new StringBuilder()); + if (!playerReceivedParts.containsKey(messageId)) playerReceivedParts.put(messageId, Unpooled.buffer()); - final StringBuilder builder = playerReceivedParts.get(messageId); + final ByteBuf buf = playerReceivedParts.get(messageId); - final String payload = payloadTextComponent.content(); + buf.writeBytes(chunkBuf); // the remaining is the chunk since we read all of them - builder.append(payload); - - playerReceivedParts.put(messageId, builder); + playerReceivedParts.put(messageId, buf); if (payloadState == PayloadState.DONE) { playerReceivedParts.remove(messageId); - final byte[] decryptedFullPayload = Encryptor.decrypt( - Ascii85.decode(builder.toString()), - bot.config.chomeNSMod.password - ); + final byte[] bytes = new byte[buf.readableBytes()]; + buf.readBytes(bytes); - final Packet packet = deserialize(decryptedFullPayload); + final Packet packet = deserialize(bytes); if ( packet == null ||