refactor(parsers): flatten nested bytesAvailable guards on UserProfile + GetGuestRoomResult

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.
This commit is contained in:
simoleo89
2026-05-18 20:57:28 +02:00
parent 892d16b393
commit d740f833eb
2 changed files with 39 additions and 26 deletions
@@ -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;
}
@@ -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;
}