fix: opcode-196 desync after player inventory - #6
Closed
renanchavess wants to merge 1 commit into
Closed
Conversation
|
This PR is stale because it has been open 45 days with no activity. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes parsing misalignment after 0xF5 (GameServerPlayerInventory) that caused the client to interpret residual bytes as 0xC4 (196) and abort the processing of aggregated packets, resulting in visual delays in creature deaths and equipment swaps.
Makes the default handler for unmapped opcodes resilient: logs metadata and resynchronizes to the next valid opcode instead of interrupting.
Problem
After receiving 0xF5 (PlayerInventory), the client left unread bytes in the buffer.
The first residual byte was treated as if it were a 0xC4 (196) opcode, leading to parser exceptions and blocking subsequent opcodes from the same packet.
Symptoms: sprite took a long time to change to "dead", equipment updates were delayed, map errors ("no thing at pos…").
Root Cause
PlayerInventory uses variable encoding for counting (1–4 bytes depending on the value). The parser was not correctly consuming this variation, leaving leftovers in the buffer.
The default handler for unknown opcodes interrupted processing at the first residual byte.
Changes
Inventory parser updated to correctly consume the variable encoding for counting:
src/client/protocolgameparse.cpp:3293-3316
Routing for GameServerPlayerInventory (245) now directs to the parser:
src/client/protocolgameparse.cpp:577-579
Resilient default handler:
Logs opcode, prevOpcode, readPos, unread, msgSize and writes only the unread segment (UNREAD_HEX) to packet.log.
Re-synchronizes by searching for nearby candidate opcodes (0xF5, 0xC3, 0xC6, 0xC7, and other common ones); if not found, skips unreading altogether.
src/client/protocolgameparse.cpp:608-659
Evidence
Before the fix, recurring entries in otclient.log and packet.log:
“unhandled opcode 0xC4 (196), prev opcode is 0xF5 (245), unread …”
After the fix, PlayerInventory fully consumes its payload and the default handler avoids aborts, allowing subsequent opcodes in the packet to be processed without delay.
Impact
Eliminates delays in visual updates (death and equipment) caused by aborts of aggregated packets.
Improves diagnostics in case of future unknown opcodes, without interrupting the game flow. Compatibility
Server-side does not emit 0xC4; Cyclopedia messages for houses use 0xC3, 0xC6, 0xC7. The fix maintains compatibility with the current protocol.
No changes to public APIs; only internal parsing and logging.
How to Test
Log into the game, trigger events that activate PlayerInventory and quick actions (kill creature, change equipment).
Verify that:
Creature sprite changes to "dead" immediately.
Equipment updates without delay.
otclient.log does not show new entries of "unhandled opcode 0xC4".
If any unknown opcode occurs, packet.log contains UNREAD_HEX only for the unread portion, and the client continues processing.
Notes
Code references:
Switch for PlayerInventory: src/client/protocolgameparse.cpp:577-579
Corrected parser: src/client/protocolgameparse.cpp:3293-3316
Default handler and re-synchronization: src/client/protocolgameparse.cpp:608-659