Branch: feature/modern-32bit-opcodes
Commit: 4e76d64ca8ae707ffb2e1e39f1a9f76160342778
Support 4-byte modern opcodes and add the 4.4.2.60895 opcode table
Clients from 4.4.0 carry an opcode group in the upper 16 bits and send the
opcode as a uint32: both directions, and inside SMSG_COMPRESSED_PACKET
(TrinityCore cata_classic WorldSocket::WritePacketToBuffer). The modern side
assumed 16 bits everywhere.
Opcode size
- OpcodeTableGenerator splits the current-to-universal table by the opcode's
upper 16 bits and emits each build's opcode size: 4 when any of its opcodes
has group bits, else 2. A flat table for 4.4.2 would need 5.4M slots; its
22 groups need about 2,600. - ModernVersion.OpcodeSize carries that size to the WorldPacket receive
constructor, ModernPacketBody (plain body, compressed envelope, Adler-32
input) and the deflate stream. Group 0 keeps an array of its own, so a
16-bit build's lookup is still one bounds check and one load. - SniffFile writes PKT 3.1, the format of TrinityCore's packet log, for a
stream with 4-byte opcodes, because PKT 2.1 stores a server opcode in 2
bytes. 16-bit builds and the legacy capture stay on PKT 2.1, byte for byte. - The legacy capture no longer copies every client packet to prepend two
bytes for SniffFile to strip.
4.4.2.60895 opcode table
- The 3.4.3.54261 table's names, in the same order, with the 4.4.2 client's
values: from docs/protocol/4.4.2.60895, and from TrinityCore cata_classic
for the connection opcodes the reference does not list. The two agree on
all 1,662 names they share. - HermesProxy's own names for 3.4.3 opcodes (SMSG_FORCE_RUN_SPEED_CHANGE,
SMSG_SEASON_INFO, the four names on SMSG_NPC_INTERACTION_OPEN_RESULT, ...)
are matched to their 4.4.2 opcode through WowPacketParser's 3.4.3 and 4.4.2
tables. 910 of the 923 3.4.3 opcodes map. The rest stay 0: those gone in
4.4.2 (SMSG_MOTD, SMSG_SET_FORCED_REACTIONS and its request, the
stable-slot and pet-swap requests, the conquest formula pair,
SMSG_SET_ALL_TASK_PROGRESS, SMSG_AUCTION_REMOVED_NOTIFICATION,
CMSG_GUILD_AUTO_DECLINE_INVITATION), and SMSG_DESTROY_OBJECT and
SMSG_COMPRESSED_UPDATE_OBJECT, which sit on unrelated 3.4.3 opcodes and
are never sent. - CMSG_AUCTION_LIST_OWNED_ITEMS and CMSG_AUCTION_LIST_BIDDED_ITEMS follow the
3.4.3 opcode rather than the name: it has exactly the layout of 4.4.2's
OWNER/BIDDER request, while 4.4.2's own OWNED/BIDDED are the retail-style
requests with a sort list. - ClientVersionBuild.V4_4_2_60895 is not a supported client yet.
No build HermesProxy serves has group bits, so nothing on the wire changes.
On the M4 (medium job) the modern opcode lookup measures 534.5 -> 533.3 ns
per 1024 and the send path stays within 0.5%. Played 3.4.3 against
AzerothCore playerbots.
Also fixes SocketSendTimeoutTests on macOS, where a zero SO_SNDBUF is
rejected with EINVAL; it gets the smallest buffer macOS accepts. The test
had never run on macOS CI: only feature/** branches run tests there.
Refs #202
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com