UserProfileComposer appends getTotalBadges() as the final int of the profile
packet, but UserProfileParser returned after displayOrder and never read it, so
the _totalBadges getter always returned its flush default 0. The extended-profile
summary (UserContainerView) reads userProfile.totalBadges with a
`?? userBadges.length` fallback, but since the getter returned 0 (not undefined)
the fallback never triggered and the badge count rendered 0.
Add a 5th optional-trailing tier reading the int (bytesAvailable-guarded so older
servers that don't emit it still parse cleanly).
getActiveRoomSessionSnapshot() caches the frozen snapshot keyed on the session
reference, but RoomDataHandler (tradeMode/groupId/isGuildRoom/doorMode/allowPets)
and RoomPermissionsHandler (controllerLevel/owner) mutate those fields on the
same session object without invalidating the cache. Any consumer reading a
mutable field via useActiveRoomSessionSnapshot would get stale data and never
re-render.
Expose invalidateRoomSessionSnapshot() on IRoomHandlerListener and call it from
both handlers after they mutate the session.
RequestPrefixesComposer (REQUEST_PREFIXES=7011) and DeletePrefixComposer
(DELETE_PREFIX=7013) are used by the client's useInventoryPrefixes but were
never registered in NitroMessages, so SendMessageComposer(new RequestPrefixesComposer())
resolved to composer id -1 ("Unknown Composer") and the packet was dropped — the
Prefixes panel never even requested its list, so the incoming registrations from
the previous commit had nothing to decode. Both headers align with the emulator
(RequestUserPrefixesEvent / DeletePrefixEvent = 7011 / 7013).
Completes the previous incoming-side fix; the prefix list + delete flow now goes
out end-to-end.
UserPrefixesEvent (7001), PrefixReceivedEvent (7002) and
ActivePrefixUpdatedEvent (7003) were defined and exported but never mapped in
NitroMessages, so the client's useInventoryPrefixes listeners could never fire:
opening the Prefixes inventory tab sends RequestUserPrefixes, the emulator
replies with UserPrefixesComposer (7001) and the client had no decoder for it
(panel stayed empty); purchase (7002) and active-prefix changes (7003) likewise
didn't update live. Only the sibling USER_NICK_ICONS (7004) was registered,
which is why this went unnoticed.
Register the three incoming headers next to USER_NICK_ICONS.
Arcturus' Habbo.connect() runs when the SSOTicket packet is handled and needs the machineId, which is set by the UniqueID packet. Sending the SSO ticket first made such servers reject the login (WS closed with "Bye") because the fingerprint hadn't arrived yet. Send UniqueID before the SSO ticket so the machineId is available when the server processes the login.
Dev's committed yarn.lock was stale vs package.json (the single-8.19.0
pixi dedup landed on main but not Dev), so CI's yarn install
--frozen-lockfile failed. Regenerated lockfile (Yarn 1.22.22) — verified
--frozen-lockfile passes.
Add FurniEditorImportTextComposer (outgoing 10049) + FurniEditorImportText
ResultEvent/Parser (incoming 10049: found, name, description, classname),
register both in NitroMessages and export from the furnieditor barrels.
Lets the editor pull official names/descriptions from a server-fetched
Habbo furnidata URL.
Append optional sort field + direction to FurniEditorSearchComposer so
the server can order the full result set (not just the visible page).
Defaults id/asc keep existing callers working.
Add FurniEditorImportTextComposer (outgoing 10049) + FurniEditorImportText
ResultEvent/Parser (incoming 10049: found, name, description, classname),
register both in NitroMessages and export from the furnieditor barrels.
Lets the editor pull official names/descriptions from a server-fetched
Habbo furnidata URL.
Append optional sort field + direction to FurniEditorSearchComposer so
the server can order the full result set (not just the visible page).
Defaults id/asc keep existing callers working.
Design for sourcing furni display names from furnidata JSON (DB keeps technical data), with a live delta-broadcast pipeline (emulator file-watch -> renderer patch -> client refresh) and a security hardening section. Cross-repo reference copy.
Add SessionDataManager.mergeFurnitureDataFromUrl() + FurnitureDataLoader.mergeFromUrl()
to merge a single furnidata chunk (e.g. a custom tier) into the live floor/wall maps at
runtime, returning the added entries so callers can also refresh the RoomContentLoader.
Lets newly added furniture appear without a full client reload.