diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index 34bf4a582..2e9523e29 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -5,7 +5,6 @@ import ch.qos.logback.classic.Logger; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import emu.grasscutter.Grasscutter.ServerDebugMode; import emu.grasscutter.auth.AuthenticationSystem; import emu.grasscutter.auth.DefaultAuthentication; import emu.grasscutter.command.CommandMap; @@ -14,6 +13,7 @@ import emu.grasscutter.command.PermissionHandler; import emu.grasscutter.config.ConfigContainer; import emu.grasscutter.data.ResourceLoader; import emu.grasscutter.database.DatabaseManager; +import emu.grasscutter.net.packet.PacketOpcodesUtils; import emu.grasscutter.plugin.PluginManager; import emu.grasscutter.plugin.api.ServerHook; import emu.grasscutter.scripts.ScriptLoader; @@ -98,6 +98,10 @@ public final class Grasscutter { Tools.createGmHandbook(); exitEarly = true; } + case "-dumppacketids" -> { + PacketOpcodesUtils.dumpPacketIds(); + exitEarly = true; + } case "-gachamap" -> { Tools.createGachaMapping(DATA("gacha_mappings.js")); exitEarly = true; diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java index abb006fc9..3d79a196d 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java @@ -1,7 +1,5 @@ package emu.grasscutter.net.packet; -import java.util.HashSet; - public class PacketOpcodes { // Empty public static final int NONE = 0; @@ -1856,12 +1854,4 @@ public class PacketOpcodes { public static final int WorldRoutineTypeCloseNotify = 3502; public static final int WorldRoutineTypeRefreshNotify = 3525; - // Unknown - - public static final HashSet BANNED_PACKETS = new HashSet<>() { - { - this.add(PacketOpcodes.WindSeedClientNotify); - this.add(PacketOpcodes.PlayerLuaShellNotify); - } - }; } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java deleted file mode 100644 index ff7be1e45..000000000 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -package emu.grasscutter.net.packet; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Field; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -public class PacketOpcodesUtil { - private static Int2ObjectMap opcodeMap; - - static { - opcodeMap = new Int2ObjectOpenHashMap(); - - Field[] fields = PacketOpcodes.class.getFields(); - - for (Field f : fields) { - if(f.getType().equals(int.class)) { - try { - opcodeMap.put(f.getInt(null), f.getName()); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - public static String getOpcodeName(int opcode) { - if (opcode <= 0) return "UNKNOWN"; - return opcodeMap.getOrDefault(opcode, "UNKNOWN"); - } - - public static void dumpOpcodes() { - try { - BufferedWriter out = new BufferedWriter(new FileWriter("opcodes.ini")); - for (Int2ObjectMap.Entry entry : opcodeMap.int2ObjectEntrySet()) { - out.write(String.format("%04X=%s%s", entry.getIntKey(), entry.getValue(), System.lineSeparator())); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java new file mode 100644 index 000000000..fc6c5dba0 --- /dev/null +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtils.java @@ -0,0 +1,68 @@ +package emu.grasscutter.net.packet; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.Grasscutter; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +public class PacketOpcodesUtils { + private static Int2ObjectMap opcodeMap; + + public static final Set BANNED_PACKETS = Set.of( + PacketOpcodes.WindSeedClientNotify, + PacketOpcodes.PlayerLuaShellNotify + ); + + public static final Set LOOP_PACKETS = Set.of( + PacketOpcodes.PingReq, + PacketOpcodes.PingRsp, + PacketOpcodes.WorldPlayerRTTNotify, + PacketOpcodes.UnionCmdNotify, + PacketOpcodes.QueryPathReq + ); + + static { + opcodeMap = new Int2ObjectOpenHashMap(); + + Field[] fields = PacketOpcodes.class.getFields(); + + for (Field f : fields) { + if(f.getType().equals(int.class)) { + try { + opcodeMap.put(f.getInt(null), f.getName()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + public static String getOpcodeName(int opcode) { + if (opcode <= 0) return "UNKNOWN"; + return opcodeMap.getOrDefault(opcode, "UNKNOWN"); + } + + public static void dumpPacketIds() { + try (FileWriter writer = new FileWriter("./PacketIds_" + GameConstants.VERSION + ".json")) { + // Create sorted tree map + Map packetIds = opcodeMap.int2ObjectEntrySet().stream() + .filter(e -> e.getIntKey() > 0) + .collect(Collectors.toMap(Int2ObjectMap.Entry::getIntKey, Int2ObjectMap.Entry::getValue, (k, v) -> v, TreeMap::new)); + // Write to file + writer.write(Grasscutter.getGsonFactory().toJson(packetIds)); + Grasscutter.getLogger().info("Dumped packet ids."); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java index 0f6998274..7a8c4b8b1 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java +++ b/src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java @@ -95,7 +95,7 @@ public class GameServerPacketHandler { // Log unhandled packets if (GAME_INFO.logPackets == ServerDebugMode.MISSING) { - Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtil.getOpcodeName(opcode)); + Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + emu.grasscutter.net.packet.PacketOpcodesUtils.getOpcodeName(opcode)); } } } diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index 096a3a35d..5d184853c 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -9,7 +9,7 @@ import emu.grasscutter.game.Account; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.packet.PacketOpcodesUtil; +import emu.grasscutter.net.packet.PacketOpcodesUtils; import emu.grasscutter.server.event.game.SendPacketEvent; import emu.grasscutter.utils.Crypto; import emu.grasscutter.utils.FileUtils; @@ -126,7 +126,7 @@ public class GameSession implements GameSessionManager.KcpChannel { } public void logPacket( String sendOrRecv, int opcode, byte[] payload) { - Grasscutter.getLogger().info(sendOrRecv + ": " + PacketOpcodesUtil.getOpcodeName(opcode) + " (" + opcode + ")"); + Grasscutter.getLogger().info(sendOrRecv + ": " + PacketOpcodesUtils.getOpcodeName(opcode) + " (" + opcode + ")"); System.out.println(Utils.bytesToHex(payload)); } public void send(BasePacket packet) { @@ -138,7 +138,7 @@ public class GameSession implements GameSessionManager.KcpChannel { // DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can) // Stop WindSeedClientNotify from being sent for security purposes. - if(PacketOpcodes.BANNED_PACKETS.contains(packet.getOpcode())) { + if(PacketOpcodesUtils.BANNED_PACKETS.contains(packet.getOpcode())) { return; } @@ -150,7 +150,7 @@ public class GameSession implements GameSessionManager.KcpChannel { // Log switch (GAME_INFO.logPackets) { case ALL -> { - if (!loopPacket.contains(packet.getOpcode())) { + if (!PacketOpcodesUtils.LOOP_PACKETS.contains(packet.getOpcode())) { logPacket("SEND", packet.getOpcode(), packet.getData()); } } @@ -174,14 +174,6 @@ public class GameSession implements GameSessionManager.KcpChannel { } } - private static final Set loopPacket = Set.of( - PacketOpcodes.PingReq, - PacketOpcodes.PingRsp, - PacketOpcodes.WorldPlayerRTTNotify, - PacketOpcodes.UnionCmdNotify, - PacketOpcodes.QueryPathReq - ); - @Override public void onConnected(GameSessionManager.KcpTunnel tunnel) { this.tunnel = tunnel; @@ -234,7 +226,7 @@ public class GameSession implements GameSessionManager.KcpChannel { // Log packet switch (GAME_INFO.logPackets) { case ALL -> { - if (!loopPacket.contains(opcode)) { + if (!PacketOpcodesUtils.LOOP_PACKETS.contains(opcode)) { logPacket("RECV",opcode, payload); } }