Fix RPC call to use correct bit count for data transmission#1215
Merged
ksenonadv merged 1 commit intoopenmultiplayer:masterfrom Apr 27, 2026
Merged
Fix RPC call to use correct bit count for data transmission#1215ksenonadv merged 1 commit intoopenmultiplayer:masterfrom
ksenonadv merged 1 commit intoopenmultiplayer:masterfrom
Conversation
ksenonadv
approved these changes
Apr 25, 2026
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.
In LegacyNetwork::broadcastRPC, the payload length is calculated via bs.GetNumberOfUnreadBits(). That function returns "how much is left to read," not "how much was written."
This is wrong for broadcastRPC. Before the packet goes out, open.mp fires the registered onSendRPC handlers (Pawn.RakNet, anti-cheat plugins, etc.). Any handler that reads the payload - which is a perfectly normal thing to do - moves the read pointer forward. After the handler chain, GetNumberOfUnreadBits() no longer equals the full packet length. Worst case: Pawn.RakNet deliberately sets the read pointer to 8 bits past the ID byte, so for a one-byte payload it returns zero, and the client gets an RPC with an empty body.
That's exactly how it surfaced for me in Core::setWeather: the SetPlayerWeather packet (one-byte WeatherID) was arriving at the client empty, and every connected player got kicked with the "SA-MP 0.3.7 Exception" dialog on any /setweather call. The same bug silently mangles SendClientMessage/GameText broadcasts too - the string gets truncated from the start or the end depending on what the handler happened to read.
Every other method in the file (sendPacket, broadcastPacket, sendRPC) already uses GetNumberOfBitsUsed(), which returns the amount of data actually written and doesn't care about the read pointer. broadcastRPC was the odd one out.
On a vanilla server with no read handlers the readOffset stays zero, so both functions return identical results. That's why the bug sat unnoticed for years. The correct fix is straightforward: the send path shouldn't depend on what a handler did with the read pointer at all.