Commit Graph

191 Commits

Author SHA1 Message Date
simoleo89 98662e7399 test(utils): add BinaryReader / BinaryWriter round-trip coverage (23 cases)
Cover every public method on the binary pair, plus the typical packet
shape (header + mixed payload) the composer/parser pipeline emits:

- byte / short / int round-trips, including signed-edge values
  (int8 -1 from 0xFF, int16 / int32 boundaries)
- big-endian wire-order assertions on writeShort / writeInt (matches
  Arcturus's DataInputStream)
- string round-trip with length prefix + bare (includeLength=false)
  + UTF-8 multibyte byte count + empty-string edge
- writeBytes for both number[] and ArrayBuffer payloads
- readBytes slice returns an independent reader whose position is
  decoupled from the outer reader
- remaining() decrements correctly across mixed-size reads
- readFloat / readDouble decode IEEE-754 big-endian values
  (the writer has no float/double counterparts — buffer is built via
  DataView for these cases)
- writer position getter + explicit setter (caller-managed reposition)
- two independent writers concatenate cleanly into a single reader

Suite: 127/127 (was 104/104). typecheck clean.
2026-05-18 20:42:17 +02:00
simoleo89 820f791e66 Merge remote-tracking branch 'origin/main' into feat/react19-event-bus 2026-05-18 20:26:17 +02:00
duckietm b6a26fbd84 🆙 Small fix landscape's where a bit offset 2026-05-12 11:48:06 +02:00
simoleo89 ef6c661058 Renderer: surface allowUnderpass on RoomSettingsData + composer
Arcturus' RoomSettingsComposer appends an extra int at the end of the
payload — room.isAllowUnderpass() ? 1 : 0 — and RoomSettingsSaveEvent
optionally reads back a boolean at the end (if bytesAvailable > 0).
The renderer side never modeled this trailing field, so the client
couldn't surface or persist it.

- RoomSettingsData: add _allowUnderpass field + getter/setter +
  propagation through the .from() copy.
- RoomSettingsDataParser: read one trailing int after the moderation
  settings, guarded by 'if(wrapper.bytesAvailable)' so older servers
  that don't emit it keep parsing cleanly.
- SaveRoomSettingsComposer: optional trailing allowUnderpass arg. The
  server's optional-read guard tolerates 24-arg or 25-arg payloads, so
  callers that don't care about the field still send the legacy shape.

Cross-repo reference points:
- Arcturus emit side: Emulator/src/main/java/com/eu/habbo/messages/
  outgoing/rooms/RoomSettingsComposer.java line 55.
- Arcturus read side: Emulator/src/main/java/com/eu/habbo/messages/
  incoming/rooms/RoomSettingsSaveEvent.java lines 133-135.

Net client tsgo error count: 3 -> 0 on the NavigatorRoomSettings cluster.
2026-05-11 21:46:36 +02:00
simoleo89 f7a5897232 Renderer: align NitroConfig Window decl with client + fix glob .default access
Two tsgo nits that propagate to the client when the renderer is linked
in:

- packages/utils/src/NitroConfig.ts declared
  'NitroConfig?: { [index: string]: any }' on Window, but Nitro-V3
  declares 'NitroConfig?: Record<string, unknown>' in its
  react-app-env.d.ts. The two declaration-merging fragments must
  match — switching the renderer side to Record<string, unknown>
  unifies them.
- packages/assets/src/AssetManager.ts: 'import.meta.glob(...)' is
  augmented as Record<string, string> in the client's typedef, so
  'mod.default ?? mod' (defensive handling of either string or
  { default: string }) failed because mod is typed string. Cast
  inline: '((mod as { default?: string }).default ?? mod)'.

Renderer tsgo error count: 3 -> 0.
2026-05-11 21:34:47 +02:00
simoleo89 22d4e5bfb0 SocketConnection parser cast + RoomChatHandler arg-order fix
- SocketConnection.processMessage() did 'new events[0].parserClass()'
  where parserClass is typed as 'Function' on IMessageEvent (no
  construct signature). Cast to 'new () => IMessageParser' at the
  call site so the spawned instance is type-correct downstream.
- RoomChatHandler dispatched RoomSessionChatEvent with the args in
  the wrong order: '[]' (intended as the 'links' array) was landing
  in the 'chatColours' string slot. Swap to '"", []' so links go
  to position 8 and chatColours stays a string.
2026-05-11 21:10:04 +02:00
simoleo89 5ea3201e31 Align with Pixi v8: Filter[] union, WebGLRenderer narrow, ImageLike
Four sites where Pixi v8's stricter typing tripped tsgo:

- AvatarImage: container.filters is typed as 'readonly Filter[] | null'
  in v8 (no longer a single-Filter union). The old fallback branch
  'else container.filters = [container.filters, …]' tried to treat a
  readonly array as a single Filter; collapsed to the array-spread
  path which now covers both undefined and non-empty cases. Added
  Filter to the pixi.js import.
- FurnitureBadgeDisplayVisualization.updateSprite() had a 4-arg
  override (sprite, asset, scale, layerId) of the parent's 2-arg
  signature (scale, layerId). The sprite/asset were never used from
  the parameters — the body only mutated 'sprite'. Refactored to
  fetch the sprite via this.getSprite(layerId) inside the override
  body so the signature matches the base.
- ExtendedSprite: 'renderer.gl' / 'glRenderTarget.resolveTargetFramebuffer'
  exist only on WebGLRenderer / GlRenderTarget (not the WebGPU
  variants). The runtime check 'renderer.type === RendererType.WEBGL'
  guarantees this; cast at the boundary to satisfy the typechecker.
- TextureUtils.generateImage: Pixi v8's Extractor.image() returns the
  union ImageLike (HTMLCanvasElement | HTMLImageElement); the public
  signature promises HTMLImageElement. Cast at return — the Pixi
  default backend returns HTMLImageElement here.
2026-05-11 21:09:59 +02:00
simoleo89 b42f989e28 RoomEnterComposer: optional spawnX/spawnY for reconnect
Arcturus' RequestRoomLoadEvent reads the two extra ints only when
the inbound packet has 8+ bytes remaining after roomId+password, so
the renderer can send 2-arg or 4-arg payloads against the same
header. The client already calls 'new RoomEnterComposer(roomId,
password, spawnX, spawnY)' in two places inside RoomSession /
RoomSessionManager (the reconnect/respawn flow) — the composer
signature is what was lagging behind.

Server-side reference:
Arcturus-Morningstar-Extended/Emulator/src/main/java/com/eu/habbo/
messages/incoming/rooms/RequestRoomLoadEvent.java
2026-05-11 21:09:51 +02:00
simoleo89 999b8187d6 Fix PetBreedingMessageParser bytesAvailable check
bytesAvailable is a boolean (IMessageDataWrapper.bytesAvailable: boolean,
returns 'there is at least one byte left'); the parser was doing
'wrapper.bytesAvailable < 12' as if it were a count, which both
mis-compares boolean to number and short-circuits incorrectly when
exactly 11 bytes remain.

Align with every other parser in the codebase: 'if(!wrapper ||
!wrapper.bytesAvailable) return false;'. The downstream readInt
calls already throw on truncated packets so the explicit length
check was load-bearing only against malformed inputs that wouldn't
parse anyway.
2026-05-11 21:09:41 +02:00
simoleo89 0fc38a1c71 Fix self-referential ConstructorParameters in two Wired composers
WiredRoomSettingsRequestComposer and WiredUserVariablesRequestComposer
declared 'implements IMessageComposer<ConstructorParameters<typeof Self>>'
but neither defines a constructor, so ConstructorParameters resolved
to 'any[]' and getMessageArray() returning [] (any[]) failed the
narrower base-type signature () => [].

Both composers send zero payload; type as IMessageComposer<[]>
directly + annotate the return type.
2026-05-11 21:09:37 +02:00
simoleo89 08d1efafbe Drop dead sendWhisperGroupMessage — composer never existed
IRoomSession.sendWhisperGroupMessage(userId) was declared in the
interface and implemented in RoomSession by sending 'new
ChatWhisperGroupComposer(userId)' — but no such composer class
exists in the renderer (the file was never created). The only
whisper composer is RoomUnitChatWhisperComposer, which takes
(recipientName, message, styleId), not a userId.

No client call site references sendWhisperGroupMessage (grep across
Nitro-V3/src returned zero hits). Removing the dead interface method
+ broken impl is safer than inventing a ChatWhisperGroupComposer
class with no server-side handler.
2026-05-11 21:09:31 +02:00
simoleo89 c37171a61c TS 5.7+ ArrayBuffer drift: cast where ArrayBufferLike leaked
TypeScript 5.7 split ArrayBuffer / SharedArrayBuffer at the type level
(ArrayBuffer now exposes resizable/transfer/detached etc; SharedArrayBuffer
doesn't), and parametrized the typed-array constructors so plain
Uint8Array became Uint8Array<ArrayBufferLike>.

The renderer never uses SharedArrayBuffer, so this is type-level only —
narrowing back to ArrayBuffer at the boundaries:

- BinaryReader.readBytes() / .toArrayBuffer() return the underlying
  DataView buffer; cast to ArrayBuffer.
- BinaryWriter.getBuffer() same shape.
- WsSessionCrypto.randomNonce() now returns Uint8Array<ArrayBuffer>
  (it's always backed by a plain ArrayBuffer); aesGcmEncrypt/Decrypt
  nonce parameter retyped accordingly so SubtleCrypto.encrypt accepts
  it as BufferSource.
- ArrayBufferToBase64 now accepts Uint8Array | ArrayBufferLike directly
  (pako/inflate hands back Uint8Array<ArrayBuffer> which the old
  ArrayBuffer-only signature rejected).
2026-05-11 21:09:22 +02:00
simoleo89 afb5f33ec2 fix(api): IRoomSession.password + sendBackgroundMessage + optional chatColour
The IRoomSession interface was missing three things that have always
existed on the RoomSession implementation:

- `password: string` — the room session's join password (used by the
  reconnect flow in RoomSessionManager).
- `sendBackgroundMessage(backgroundImage, backgroundStand, backgroundOverlay, backgroundCard?)`
  — sends the profile-background composer (used by the React client's
  BackgroundsView).

Plus a signature relaxation:
- `sendChatMessage` / `sendShoutMessage` `chatColour` is now optional.
  The implementation already accepted `undefined` (the composer forwards
  it through), and every historical call site in the React client passes
  only 2 args — making the 3rd optional simply types reality.

Net renderer typecheck: 26 → 23.
The change also drops 7 errors on the consumer side
(see ../Nitro-V3 typecheck after the workspace link picks this up).

CLAUDE.md gotchas updated to reflect the new interface contract.
2026-05-10 21:48:49 +02:00
simoleo89 ddb7222b66 chore: bump TypeScript pins to ^6.0.3 across all 12 workspaces + thumbmarkjs 1.9 + add CLAUDE.md
Each workspace package was still pinning `typescript: ~5.5.x` or
`~5.8.2` in its own devDependencies even though the root bumped to 6.0.3
in 60b1143. The pins were dead (yarn 1 hoists from root) but they're
misleading when reading a single package.json. Bring them all to
`^6.0.3` to match the root.

Other:
- @thumbmarkjs/thumbmarkjs 1.8.1 → 1.9.0 (root + communication package)
- yarn.lock regenerated from a clean install (vitest 4 hoisting was
  flaking on the patch vite bump; reverted vite to ^8.0.10)

Adds CLAUDE.md at the repo root: short project context for future
sessions — stack, the 12-workspace layout, the React-friendly v2.1.0
additions (`subscribe()`, `subscribeMessage()`, snapshot getters), build
scripts, and known gotchas (`SessionDataManager.getUserData` does NOT
exist; sendChat* expects 3 args; dispatchEvent is sync).
2026-05-10 21:29:50 +02:00
simoleo89 87cf47847c feat(events,session): add React-friendly subscribe APIs and snapshot getters
Adds backwards-compatible primitives needed to consume the renderer from
React 19 hooks (useSyncExternalStore, use(), TanStack Query) without
re-architecting the event bus.

- EventDispatcher.subscribe(type, cb): () => void — unsubscriber-returning
  wrapper matching the useSyncExternalStore subscribe signature.
- CommunicationManager.subscribeMessage(eventCtor, handler): () => void —
  packet-stream equivalent.
- SessionDataManager.getUserDataSnapshot() and
  RoomSessionManager.getActiveRoomSessionSnapshot() — referentially-stable
  read-only views invalidated through new SESSION_DATA_UPDATED and
  ROOM_SESSION_UPDATED events.

All additive; existing addEventListener/removeEventListener / IRoomSession
APIs are unchanged. Bumps renderer to 2.1.0.
2026-05-10 19:16:32 +02:00
Lorenzune f7fc502685 Improve mobile room interaction handling 2026-05-07 21:21:48 +02:00
Lorenzune 5fc4564467 Merge remote-tracking branch 'duckie/main' into merge-duckie-main-2026-05-06
# Conflicts:
#	packages/communication/src/messages/parser/room/unit/RoomUnitInfoParser.ts
#	packages/communication/src/messages/parser/user/data/UserProfileParser.ts
#	packages/events/src/session/RoomSessionUserFigureUpdateEvent.ts
#	packages/session/src/handler/RoomUsersHandler.ts
2026-05-06 04:23:13 +02:00
duckietm 7a6092ed7e 🆙 Small update 2026-05-04 15:28:19 +02:00
duckietm 151a3db2f4 🆙 Fix BlackHoles 2026-05-04 12:53:18 +02:00
duckietm 6ab93ee146 🆙 Fixed the Door not visable when window is on wall 2026-05-04 12:01:45 +02:00
duckietm 2f7b80e894 🆕 Card Background 2026-05-04 08:44:40 +02:00
duckietm 43dc054fed 🆙 Floorplan fix 2026-04-30 07:57:31 +02:00
duckietm 853204a5b8 🆕 Effect selection in user dropdown 2026-04-29 13:23:30 +02:00
duckietm 2a707c3b8d 🆙 Cleanup log in console 2026-04-28 09:41:37 +02:00
duckietm d34f82c716 🆙 Bump renderer to V8.18.1 and replace clientjs with a better solution 2026-04-28 09:14:49 +02:00
Lorenzune 9abec36f02 Merge remote-tracking branch 'duckie/main' into duckie-live-merge-2026-04-21 2026-04-25 13:34:15 +02:00
duckietm 455b75e41d 🆙 CryptoV2 2026-04-24 16:24:02 +02:00
duckietm e1cc87afa3 🆙 Fix background clipping 2026-04-24 13:55:18 +02:00
duckietm 7957a8f7f3 🆕 Handshake on connect 2026-04-23 15:57:24 +02:00
Lorenzune 7fa8eff751 Merge latest duckie renderer main 2026-04-21 11:53:28 +02:00
Lorenzune c37c7005fc Fix prefix composer imports after duckie merge 2026-04-21 11:23:38 +02:00
Lorenzune 1dede2c098 Merge remote-tracking branch 'duckie-temp/main' into duckie-merge-2026-04-21
# Conflicts:
#	packages/communication/src/NitroMessages.ts
#	packages/communication/src/messages/incoming/IncomingHeader.ts
#	packages/communication/src/messages/outgoing/OutgoingHeader.ts
2026-04-21 11:20:02 +02:00
Lorenzune 7bf552824f Sync renderer safety push 2026-04-21 08:57:35 +02:00
duckietm 078bba0780 🆙 Make have_offer read from emu 2026-04-17 14:24:15 +02:00
duckietm 4b598fc717 Revert "Merge pull request #48 from simoleo89/feature/catalog-admin-composers"
This reverts commit 67c8dd42cd, reversing
changes made to bc6bd8764d.
2026-04-17 14:03:47 +02:00
DuckieTM 67c8dd42cd Merge pull request #48 from simoleo89/feature/catalog-admin-composers
Feature/catalog admin composers
2026-04-17 13:56:46 +02:00
duckietm bc6bd8764d 🆙 Fix Catalog Editor 2026-04-17 13:53:07 +02:00
duckietm 2c2f03f20e 🔥 Fix Avatar buddy they are now 100% as habbo 2026-04-17 11:48:38 +02:00
duckietm 282fd6f6bd 🆙 New misc clothing 2026-04-16 13:36:17 +02:00
duckietm bbedf2e5fe 🆙 Merge Dev to Prod 2026-04-14 11:57:23 +02:00
Life 1e3d6a335c Merge branch 'Dev' into feature/catalog-admin-composers 2026-04-13 17:51:16 +02:00
DuckieTM d2a36940d5 Merge branch 'Dev' into feat/wired-fixes-apr08 2026-04-13 17:01:56 +02:00
Life 04d172c735 feat: add catalog admin composers for page images and icon
- CatalogAdminSavePageImagesComposer (header 10060): pageId, headerImage, teaserImage
- CatalogAdminSavePageIconComposer (header 10061): pageId, iconId
- Registered in OutgoingHeader, catalog index, and NitroMessages
- Server handler required in Arcturus to process these packets
2026-04-10 22:22:36 +02:00
duckietm 399999f23d 🆙 Memory usage fixes 2026-04-10 11:42:30 +02:00
duckietm 37f817a098 🆙 Added Youtube Brtoadcast 2026-04-10 11:22:45 +02:00
duckietm a92f2f0603 🆙 Youtube 2026-04-09 15:36:43 +02:00
duckietm 85d3422e86 🆙 Renderer Logic Youtube Broadcast 2026-04-09 11:51:32 +02:00
duckietm 79d51246ec 🆙 Added username to send badge 2026-04-08 14:08:00 +02:00
Lorenzune 5b69407ecb Merge remote-tracking branch 'origin/main' into merge/duckietm-main-20260407 2026-04-07 15:27:01 +02:00
Lorenzune fd40a74396 feat: add builders club communication support 2026-04-07 14:40:51 +02:00