github Xian55/HermesProxy v4.5.0-feature-modern-32bit-opcodes-4e76d64
Pre-release: feature/modern-32bit-opcodes @ 4e76d64 — Support 4-byte modern opcodes and add the 4.4.2.60895 opcode table

latest releases: v4.5.58, v4.5.0-feature-cata-442-csv-00dd465, v4.5.57...
pre-release3 hours ago

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

Don't miss a new HermesProxy release

NewReleases is sending notifications on new releases.