From d740f833eb1bfd214826b35eac310901a764f744 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 18 May 2026 20:57:28 +0200 Subject: [PATCH] refactor(parsers): flatten nested bytesAvailable guards on UserProfile + GetGuestRoomResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two parsers handle "one tier of optional trailing fields per emulator release" via nested if(wrapper.bytesAvailable) chains. The semantics were correct but each new block sat one extra indent deeper than the previous one, and adding tier N+1 quietly meant re-indenting everything above it. Replaced with a flat early-return chain that's diff-friendly when the next emulator version ships a new trailing block: if(!wrapper.bytesAvailable) return true; // block N reads if(!wrapper.bytesAvailable) return true; // block N+1 reads … Functionally equivalent — defaults still come from flush(), older servers still bail at whichever tier they don't ship. Each block is now also documented inline so the order/contract is obvious without cross-referencing Arcturus. In UserProfileParser, also straightened the cardBackgroundId tier: was an inline `(wrapper.bytesAvailable ? readInt() : 0)` mid-block; now a proper `if(!bytesAvailable) return true;` guard between blocks, matching the rest of the chain. --- .../GetGuestRoomResultMessageParser.ts | 19 +++++--- .../parser/user/data/UserProfileParser.ts | 46 +++++++++++-------- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/packages/communication/src/messages/parser/navigator/GetGuestRoomResultMessageParser.ts b/packages/communication/src/messages/parser/navigator/GetGuestRoomResultMessageParser.ts index 0595de2..91e5654 100644 --- a/packages/communication/src/messages/parser/navigator/GetGuestRoomResultMessageParser.ts +++ b/packages/communication/src/messages/parser/navigator/GetGuestRoomResultMessageParser.ts @@ -45,12 +45,19 @@ export class GetGuestRoomResultMessageParser implements IMessageParser this.data.canMute = wrapper.readBoolean(); this._chat = new RoomChatSettings(wrapper); - if(wrapper.bytesAvailable) - { - this._hotelTimeZoneId = wrapper.readString(); - this._hotelCurrentTimeMs = Number(wrapper.readString()) || 0; - if(wrapper.bytesAvailable) this._roomItemLimit = wrapper.readInt(); - } + // Optional trailing blocks, one tier per emulator release: + // block 1: hotel timezone id + current time ms (2 strings) + // block 2: room item limit (1 int) + // Flat early-return chain so an older server stops cleanly at + // whichever block it doesn't ship. Defaults from flush(). + if(!wrapper.bytesAvailable) return true; + + this._hotelTimeZoneId = wrapper.readString(); + this._hotelCurrentTimeMs = Number(wrapper.readString()) || 0; + + if(!wrapper.bytesAvailable) return true; + + this._roomItemLimit = wrapper.readInt(); return true; } diff --git a/packages/communication/src/messages/parser/user/data/UserProfileParser.ts b/packages/communication/src/messages/parser/user/data/UserProfileParser.ts index ef07255..4c24ab2 100644 --- a/packages/communication/src/messages/parser/user/data/UserProfileParser.ts +++ b/packages/communication/src/messages/parser/user/data/UserProfileParser.ts @@ -82,29 +82,35 @@ export class UserProfileParser implements IMessageParser this._secondsSinceLastVisit = wrapper.readInt(); this._openProfileWindow = wrapper.readBoolean(); - if(wrapper.bytesAvailable) - { - this._backgroundId = wrapper.readInt(); - this._standId = wrapper.readInt(); - this._overlayId = wrapper.readInt(); + // Optional trailing blocks, one tier per emulator release: + // block 1: background / stand / overlay (3 ints) + // block 2: card background (1 int) + // block 3: nick icon (1 string) + // block 4: prefix decoration set (6 strings) + // Each tier early-returns to keep the parser tolerant of older + // servers that don't ship the later blocks. Defaults set by flush(). + if(!wrapper.bytesAvailable) return true; - this._cardBackgroundId = (wrapper.bytesAvailable ? wrapper.readInt() : 0); + this._backgroundId = wrapper.readInt(); + this._standId = wrapper.readInt(); + this._overlayId = wrapper.readInt(); - if(wrapper.bytesAvailable) - { - this._nickIcon = wrapper.readString(); + if(!wrapper.bytesAvailable) return true; - if(wrapper.bytesAvailable) - { - this._prefixText = wrapper.readString(); - this._prefixColor = wrapper.readString(); - this._prefixIcon = wrapper.readString(); - this._prefixEffect = wrapper.readString(); - this._prefixFont = wrapper.readString(); - this._displayOrder = wrapper.readString(); - } - } - } + this._cardBackgroundId = wrapper.readInt(); + + if(!wrapper.bytesAvailable) return true; + + this._nickIcon = wrapper.readString(); + + if(!wrapper.bytesAvailable) return true; + + this._prefixText = wrapper.readString(); + this._prefixColor = wrapper.readString(); + this._prefixIcon = wrapper.readString(); + this._prefixEffect = wrapper.readString(); + this._prefixFont = wrapper.readString(); + this._displayOrder = wrapper.readString(); return true; }