docs(claude): RoomUnitParser per-user borderId wire contract

Document that the per-user borderId int in RoomUsersComposer (Arcturus
Infostand Borders) must be read unconditionally inside the per-user
loop in RoomUnitParser, never wrapped in a bytesAvailable guard. Calls
out the failure modes on both server shapes (emits / doesn't emit)
explicitly so the next contributor doesn't re-introduce the guard
"for safety" the way it was earlier today. Points future
trailing-int additions at the same parser block for documentation.
This commit is contained in:
simoleo89
2026-05-19 22:17:51 +02:00
parent 1bad1b20ca
commit e897fec56e
+29
View File
@@ -113,6 +113,35 @@ accepts an optional `allowUnderpass` arg at the end of its parameter
list; the server-side `RoomSettingsSaveEvent` reads it under
`packet.bytesAvailable() > 0`.
### `RoomUnitParser` per-user `borderId` (Infostand Borders wire contract)
`RoomUsersComposer` on Arcturus (post `54259f8` / fork commit `8f8f568`
"Infostand Borders") appends `appendInt(getInfostandBorder())` at the
end of EVERY user record — habbo, bot, rentable bot — using `0` as the
constant for records without a real border. To stay wire-aligned with
that, `RoomUnitParser` reads `user.borderId = wrapper.readInt();`
unconditionally inside the per-user loop, after
`roomEntryMethod` / `roomEntryTeleportId`.
DO NOT wrap this in a `wrapper.bytesAvailable ? readInt() : 0` guard.
`bytesAvailable` is a boolean meaning "any bytes left in the WHOLE
packet?" — not "any bytes left for THIS user". For any non-last user
the guard evaluates `true` (next user's bytes follow) and reads, which
is fine ONLY by coincidence when the server emits borderId per user.
On a server that doesn't emit it, the guard steals 4 bytes from the
next record and cascade-corrupts the whole roster (symptom: users not
seeing each other on room enter). On a server that DOES emit it,
skipping the read leaves 4 unconsumed bytes per record and produces
the same corruption. Both shapes are wrong in a loop; unconditional
read paired with a server contract that always emits is the only
correct combination.
If you ever need to pair this parser with an older Arcturus that
doesn't emit per-user borderId, the fix is on the server side (add
the cherry-pick), not the parser side. Document any future
trailing-int extension in this same place so the next reader doesn't
re-introduce a bytesAvailable guard "for safety".
### Dropped dead code: `sendWhisperGroupMessage`
`IRoomSession.sendWhisperGroupMessage(userId)` referenced a