Commit Graph

1003 Commits

Author SHA1 Message Date
simoleo89 f7e10b5f46 feat(vault): functional Guadagni (Earnings Center) window
VaultView wired to the Earnings Center packets: requests data on open, renders
real amounts/claimable per category from EarningsCenterEvent, Riscatta + Richiedili
Tutti send the claim composers, refreshes on EarningsClaimResultEvent. Category
keys match the emulator contract; reward currencies derived from reward type.
Adds the real earnings_icon assets. Wired into MainView.
2026-06-15 22:29:10 +02:00
DuckieTM 124858c0f8 Merge pull request #248 from Lorenzune/pr-restore-client-release
Restore client release workflow
2026-06-15 07:18:00 +02:00
DuckieTM 5e1e8ce654 Merge pull request #247 from simoleo89/docs/claude-md-runtime-verify
docs(CLAUDE): add Runtime verification section (Claude-in-Chrome, not headless)
2026-06-15 07:17:42 +02:00
DuckieTM 25e53e85b1 Merge pull request #246 from simoleo89/fix/marketplace-bugs
fix(marketplace): creditsWaiting reset & re-priced offer vanish
2026-06-15 07:17:20 +02:00
DuckieTM c14a6ec4d8 Merge pull request #245 from simoleo89/fix/purse-hc-status
fix(purse): HC status EXPIRED for ex-Club non-VIP users
2026-06-15 07:17:02 +02:00
DuckieTM fbbcca6dd6 Merge pull request #244 from simoleo89/fix/groups-color-picker
fix(groups): colour-picker highlight follows live selection
2026-06-15 07:16:41 +02:00
DuckieTM f57c2bd2bf Merge pull request #243 from simoleo89/fix/camera-bugs
fix(camera): delete-index reset & full-roll discard
2026-06-15 07:16:18 +02:00
DuckieTM c69ccba51d Merge pull request #242 from simoleo89/fix/modtools-bugs
fix(mod-tools): default-sanction topic id & alert typos
2026-06-15 07:15:52 +02:00
DuckieTM 75cd2791f8 Merge pull request #241 from simoleo89/fix/wired-bugs
fix(wired): @altitude scale & date-range NaN
2026-06-15 07:15:31 +02:00
DuckieTM 6fb8387afd Merge pull request #240 from simoleo89/fix/room-widget-bugs
fix(room): name-bubble, pet-fertilize chat & word-quiz bugs
2026-06-15 07:15:09 +02:00
DuckieTM 3eec31629f Merge pull request #239 from simoleo89/fix/messenger-setread-render
fix(messenger): mark thread read in an effect, not during render
2026-06-15 07:14:47 +02:00
DuckieTM abce531616 Merge pull request #238 from simoleo89/fix/inventory-state-bugs
fix(inventory): state-mutation & stale-read bugs
2026-06-15 07:14:28 +02:00
DuckieTM f1c9e1baee Merge pull request #237 from simoleo89/feat/furni-editor-create-missing
feat(furni-editor): create furnidata entry when missing (upsert Save)
2026-06-15 07:14:04 +02:00
Lorenzune dd1b8b7613 Fix release bundle chunk loading 2026-06-15 02:20:54 +02:00
Lorenzune 29cba0be2d Restore client release workflow 2026-06-15 02:16:23 +02:00
simoleo89 b27f48f2a2 feat(furni-editor): sync empty public_name from furnidata name
When a furni has a matching furnidata entry with a display name but its
items_base.public_name (the DB fallback) is empty, the editor now shows a
'Sync from furnidata' button next to the Public Name field. It reuses the
generic item update (a partial { publicName } payload) to fill the DB column
from the stored furnidata name, so the read-only fallback stops being blank.
Button shows only when the entry's classname matches, the DB field is empty,
and the furnidata name is present; it disappears after the sync re-fetch.
2026-06-14 16:41:55 +02:00
simoleo89 88d2128295 docs(furni-editor): design for syncing empty public_name from furnidata 2026-06-14 15:53:13 +02:00
simoleo89 1676b3c871 fix(furni-editor): surface upsert failures and revert optimistic name on error
When creating a furnidata entry for a furni whose sprite id is already used
by another classname, the server rejects with ID_COLLISION. The client showed
the optimistic public-name change but never reverted it, so a failed create
looked like it had succeeded. On any FurniEditorResult failure, re-fetch the
item detail to restore the true state (the error alert was already shown).
2026-06-14 14:44:25 +02:00
simoleo89 7e72578d2c docs(CLAUDE): add Runtime verification section (Claude-in-Chrome, not headless)
Captures the session learning: the client can't be verified headless (WebGL
hangs + SSO login); use the Claude-in-Chrome extension on the real logged-in
localhost:5173 session (shared SSO cookie auto-logs-in, real GPU). Toolbar
buttons are canvas → locate by screenshot + click by coordinate.
2026-06-14 13:43:52 +02:00
simoleo89 101c1b901f fix(marketplace): re-priced offer vanished when the server kept the same id
The "price raised" (case 3) handler did `set(item.offerId, item)` then an
unconditional `delete(requestedOfferId)`. When the re-priced offer kept the same
id (offerId === requestedOfferId), the set was immediately undone and the offer
disappeared from the list though it was still buyable. Delete the old key first,
then set under the new id.
2026-06-13 18:15:39 +02:00
simoleo89 26d7ccd62b fix(marketplace): reset creditsWaiting after redeeming sold offers
redeemSoldOffers optimistically removed the sold offers but never reset
creditsWaiting, so the redeem panel (gated on creditsWaiting > 0) kept rendering
"get 0 sold items for N credits" with an active Redeem button until the server
re-pushed the offers. Reset creditsWaiting to 0 on redeem.
2026-06-13 18:15:39 +02:00
simoleo89 8e82935312 fix(purse): HC status never reports EXPIRED for ex-Club (non-VIP) users
clubStatus computed `(purse.pastVipDays > 0) || (purse.pastVipDays > 0)` — the
same field twice. The first operand was meant to be `pastClubDays`, so a user who
previously had Habbo Club but never VIP got ClubStatus.NONE instead of EXPIRED,
showing the wrong HC Center status text and Buy-vs-Extend button. Use pastClubDays.
2026-06-13 18:15:36 +02:00
simoleo89 9c57d6a431 fix(groups): colour-picker highlight follows the live selection
The selected-swatch ring compared each swatch against `groupData.groupColors`,
which is only written back on save — so clicking a colour updated the local
`colors` state (and the top preview swatches) but the highlight ring never moved,
leaving the two in visible disagreement until you left and reopened the tab.
Compare against `colors[0]`/`colors[1]` (the live state) instead.
2026-06-13 18:15:34 +02:00
simoleo89 a776960650 fix(camera): full roll no longer discards the newest photo
When the roll hit CAMERA_ROLL_LIMIT the capture path alerted "full" then did
clone.pop() (dropping the NEWEST photo) and pushed the new one — so once full the
roll was pinned at the limit and every further shot just replaced the most-recent
picture. Block the shot instead (return after the alert).
2026-06-13 18:15:31 +02:00
simoleo89 d6cac249c6 fix(camera): reset selected picture index after deleting a photo
The 'delete' action spliced the selected picture out of the roll but never moved
selectedPictureIndex, so it kept pointing at the slot the deleted photo vacated —
now a different picture (or past the end), making the preview show the wrong
photo or vanish while the UI still thinks one is selected. Move the selection
back one after delete.
2026-06-13 18:15:31 +02:00
simoleo89 ed5c9296a8 fix(mod-tools): typos in moderation-action result alerts
The ModeratorActionResultMessageEvent alerts (hardcoded, not LocalizeText) read
"successfull" and "applying tht moderation action". Fix to "successful" / "the".
2026-06-13 18:15:29 +02:00
simoleo89 149b1db38c fix(mod-tools): default-sanction sent the topic array index, not the topic id
sendDefaultSanction passed `selectedTopic` (the index into the topics array) as
the CFH topic id to DefaultSanctionMessageComposer, so the emulator applied the
default sanction against whatever topic happened to sit at that array position.
The sibling sendSanction (and the topic label) correctly use
`topics[selectedTopic].id`. Pass `category.id`, and move the `category` lookup
after the `selectedTopic === -1` guard (+ a `!category` guard).
2026-06-13 18:15:29 +02:00
simoleo89 742f7ee5f7 fix(wired): date-range condition saved NaN for empty/invalid dates
The save guard `if(startDateInstance && endDateInstance)` is always true — a bad
input parses to a truthy *Invalid Date*, so `getTime()/1000` wrote NaN into the
int params. A never-configured furni was worse: the read effect only seeded the
inputs when `intData.length >= 2`, so the first save sent `new Date('')` → NaN.
Guard on `isNaN(getTime())` and seed both inputs to "now" for the empty case.
2026-06-13 18:15:26 +02:00
simoleo89 728eceab65 fix(wired): @altitude shown 100x too large and round-trip-edited wrong
`liveState.altitude` is already z*100, but the @altitude inspector rows multiplied
by 100 again (showing z*10000). The edit-commit path parses the field back as
`parsed / 100` (expecting z*100), so the displayed value and the edit parser
disagreed: tweaking the shown number wrote a wildly wrong altitude (clamped to the
40 ceiling). Display the raw `altitude` so it round-trips with the editor.
2026-06-13 18:15:26 +02:00
simoleo89 648cea698d fix(room): word-quiz countdown mutates Map value objects in place
The 1s tick did `value.secondsLeft--` on the VoteValue objects held by the
previous state Map and returned the same Map reference when nothing expired — an
in-place state mutation (breaks memoization / StrictMode double-invoke). Rebuild
new value objects in a new Map each tick (and drop expired entries).
2026-06-13 18:15:24 +02:00
simoleo89 a2f8a4dd61 fix(room): pet-fertilize chat bubble — bad localization key + wrong target user
Two bugs in the pet rebreed/fertilize chat path: the localization key had a
stray trailing semicolon (`'widget.chatbubble.petrefertilized;'`) so the lookup
failed and the raw key rendered; and the target user was resolved via
`newRoomObject = getRoomObject(event.extraParam)` but then read back by
`roomObject.id` (the speaker), so `userName` was the speaker, not the target.
Use `newRoomObject.id`.
2026-06-13 18:15:24 +02:00
simoleo89 53463b8322 fix(room): name bubbles cleared for the wrong user on USER_REMOVED
The USER_REMOVED handler for a UNIT filtered name bubbles with
`bubble.roomIndex === event.id`, which KEEPS only the leaving user's bubble and
drops everyone else's (the two sibling filters on the next lines correctly use
`!==`). When any user left view, all other floating name bubbles vanished while
the departed user's lingered. Flip to `!==`.
2026-06-13 18:15:24 +02:00
simoleo89 f873d68ee9 fix(messenger): mark thread read in an effect, not during render
FriendsMessengerThreadView called `thread.setRead()` in the render body — a side
effect during render that mutates the MessengerThread instance the messenger hook
also reads to compute the unread indicator, making unread state order-dependent
(and it would NPE if `thread` was null). Move it into a no-dependency useEffect
(runs after every commit, same cadence as before) and guard the null thread.
2026-06-13 18:15:21 +02:00
simoleo89 af6f65b194 fix(inventory): drop leaking badge pending-counter; trust server active set
sendActiveBadges incremented pendingUpdatesRef on every edit, and the BadgesEvent
handler skipped applying the server's active badges while the counter was > 0,
decrementing once per BadgesEvent. The assumption was "one BadgesEvent echo per
SetActivatedBadges" — but the emulator's UserWearBadgeEvent answers with a
UserBadgesComposer room broadcast, NOT a BadgesEvent, so nothing ever decrements
the counter. It leaks upward with every toggle/reorder/swap and then silently
drops legitimate later BadgesEvent updates (the server-authoritative active set
never reapplies). Remove the counter and always apply the server's active badges
on BadgesEvent (edits are already persisted server-side, so this is correct).
2026-06-13 18:15:19 +02:00
simoleo89 39fbfdd9e2 fix(inventory): derive active prefix from the fresh list, not a stale closure
The ActivePrefixUpdatedEvent handler set the active prefix via
`setActivePrefix(prev => { const found = prefixes.find(...) })`, reading the
`prefixes` state from the closure — which lags by a render and is stale/empty when
the prefix was added earlier in the same event batch, so `found` was undefined and
the active prefix fell back to a partial item missing icon/color/displayName. Move
the derivation inside the `setPrefixes` updater so it reads the freshly-mapped list.
2026-06-13 18:15:19 +02:00
simoleo89 9cc9ef86c0 fix(inventory): stop unseen-tracker mutating shared state arrays in place
resetItems/removeUnseen/the UnseenItemsEvent handler each did `new Map(prevValue)`
(a shallow copy) then spliced/pushed the per-category array returned by
`.get(category)` — the SAME array reference still held by the previous Map. That
mutates state outside React's data flow (breaks under StrictMode double-invoke and
any updater replay). resetItems additionally did `splice(existing.indexOf(id), 1)`
with no guard, so an id not present (indexOf === -1) spliced off the wrong LAST
element. Replace each in-place splice/push with a cloned array set back on the new
Map (filter for removals, spread+push for the merge).
2026-06-13 18:15:19 +02:00
simoleo89 74cbeccb52 feat(furni-editor): create furnidata entry when missing (upsert Save)
When a furni has no furnidata entry (furniDataEntry === null), unlock the
name/description fields instead of locking them: the Save button becomes
"Create entry" and sends the existing FurniEditorUpdateFurnidataComposer (10046),
which the emulator now upserts (creates a complete entry from items_base). The
classname-mismatch case (entry resolved by id but for a different classname)
stays locked to avoid an id collision. On success the hook already re-fetches the
detail, so the panel flips to normal edit mode. Name input prefills (placeholder)
from the DB Public Name.
2026-06-13 18:01:02 +02:00
DuckieTM 93baedf206 Merge pull request #235 from duckietm/main
Sync Main to dev
2026-06-12 16:02:40 +02:00
DuckieTM 3c9332e798 Merge pull request #234 from duckietm/Dev
Dev
2026-06-12 16:01:58 +02:00
DuckieTM d0a7d200d1 Merge pull request #230 from hotellidev/multicolorfurnifix
Fix multicolor furni names
2026-06-12 15:54:27 +02:00
DuckieTM c62e041d46 Merge pull request #229 from simoleo89/feat/installer-configurable-renderer-dir
feat(installer): make the renderer folder configurable
2026-06-12 15:53:46 +02:00
DuckieTM 419cb4cbde Merge pull request #228 from RemcoEpicnabbo/Dev
Remove trailing comma in ui-config.example
2026-06-12 15:53:05 +02:00
hotellidev caf80e5386 Merge branch 'duckietm:main' into multicolorfurnifix 2026-06-12 03:15:02 +03:00
DuckieTM 32b0e2a370 Merge pull request #233 from duckietm/Dev
🆙 100% Guild Furni Catalog Page
2026-06-11 13:16:46 +02:00
duckietm de38371069 🆙 100% Guild Furni Catalog Page 2026-06-11 13:16:29 +02:00
DuckieTM 69b643761c Merge pull request #232 from duckietm/Dev
🆙 Fix scrollbar
2026-06-11 10:31:41 +02:00
duckietm 40864cf880 🆙 Fix scrollbar 2026-06-11 10:31:24 +02:00
DuckieTM c4d7070316 Merge pull request #231 from duckietm/Dev
🆙 Added colored background to items in group furni & fix catalog price
2026-06-11 10:14:58 +02:00
duckietm 5aa9dcd650 🆙 Added colored background to items in group furni & fix catalog price 2026-06-11 10:14:27 +02:00
hotellidev afaea87bcd Fix multicolor furni names 2026-06-11 04:07:06 +03:00