From dac83e8a626fd5ebd3147ae904167fa69037ef8f Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 15 Jun 2026 20:25:48 +0200 Subject: [PATCH] docs(earnings): define emulator rewards center --- .../plans/2026-06-15-earnings-center.md | 85 ++++++++++++++++ .../2026-06-15-earnings-center-design.md | 97 +++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-15-earnings-center.md create mode 100644 docs/superpowers/specs/2026-06-15-earnings-center-design.md diff --git a/docs/superpowers/plans/2026-06-15-earnings-center.md b/docs/superpowers/plans/2026-06-15-earnings-center.md new file mode 100644 index 00000000..636c2998 --- /dev/null +++ b/docs/superpowers/plans/2026-06-15-earnings-center.md @@ -0,0 +1,85 @@ +# Earnings Center Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build an emulator-owned earnings/rewards hub for the new "Guadagni" UI, with server-side reward definitions and claim protection. + +**Architecture:** Add a focused earnings package under `com.eu.habbo.habbohotel.earnings`, wire three incoming handlers and two outgoing composers, and persist claims in a dedicated table with a unique period key. Keep reward definitions config-driven so UI/renderer work can progress independently. + +**Tech Stack:** Java 21, Maven, MariaDB SQL updates, existing Arcturus packet manager/composer patterns, JUnit tests. + +--- + +### Task 1: Map Existing Patterns + +**Files:** +- Read: `Emulator/src/main/java/com/eu/habbo/messages/PacketManager.java` +- Read: `Emulator/src/main/java/com/eu/habbo/messages/PacketNames.java` +- Read: `Emulator/src/main/java/com/eu/habbo/habbohotel/users/Habbo.java` +- Read: `Emulator/src/main/java/com/eu/habbo/messages/outgoing/MessageComposer.java` + +- [ ] Inspect packet registration and composer header lookup. +- [ ] Inspect currency grant methods on `Habbo`. +- [ ] Inspect emulator setting access APIs. +- [ ] Choose the smallest implementation that matches existing style. + +### Task 2: Add Earnings Domain + +**Files:** +- Create: `Emulator/src/main/java/com/eu/habbo/habbohotel/earnings/EarningsCategory.java` +- Create: `Emulator/src/main/java/com/eu/habbo/habbohotel/earnings/EarningsReward.java` +- Create: `Emulator/src/main/java/com/eu/habbo/habbohotel/earnings/EarningsEntry.java` +- Create: `Emulator/src/main/java/com/eu/habbo/habbohotel/earnings/EarningsClaimResult.java` +- Create: `Emulator/src/main/java/com/eu/habbo/habbohotel/earnings/EarningsCenterManager.java` + +- [ ] Define allowlisted categories and client keys. +- [ ] Load enabled flags, cooldowns, and reward values from configuration. +- [ ] Build row state for a user. +- [ ] Implement single claim and claim-all. +- [ ] Grant credits/pixels/points through existing `Habbo` APIs. + +### Task 3: Add Persistence + +**Files:** +- Create: `Database Updates/012_earnings_center.sql` + +- [ ] Create `users_earnings_claims`. +- [ ] Add unique key on `user_id`, `category`, `period_key`. +- [ ] Keep the migration additive and safe for existing databases. + +### Task 4: Add Packet Bridge + +**Files:** +- Create: `Emulator/src/main/java/com/eu/habbo/messages/incoming/earnings/RequestEarningsCenterEvent.java` +- Create: `Emulator/src/main/java/com/eu/habbo/messages/incoming/earnings/ClaimEarningsRewardEvent.java` +- Create: `Emulator/src/main/java/com/eu/habbo/messages/incoming/earnings/ClaimAllEarningsRewardsEvent.java` +- Create: `Emulator/src/main/java/com/eu/habbo/messages/outgoing/earnings/EarningsCenterComposer.java` +- Create: `Emulator/src/main/java/com/eu/habbo/messages/outgoing/earnings/EarningsClaimResultComposer.java` +- Modify: packet registration/mapping files discovered in Task 1. + +- [ ] Incoming handlers parse only category keys. +- [ ] Outgoing composers serialize rows and claim results. +- [ ] Packet names are documented for renderer alignment. + +### Task 5: Test and Build + +**Files:** +- Create: `Emulator/src/test/java/com/eu/habbo/habbohotel/earnings/EarningsCenterManagerTest.java` + +- [ ] Test disabled feature behavior. +- [ ] Test unknown category rejection. +- [ ] Test single claim success. +- [ ] Test duplicate claim rejection. +- [ ] Test claim-all partial success. +- [ ] Run focused tests. +- [ ] Run `mvn clean package`. + +### Task 6: Commit and PR + +**Files:** +- Commit all source, test, SQL, spec, and plan files. + +- [ ] Commit spec and plan. +- [ ] Commit implementation. +- [ ] Push `feat/earnings-center` to `simoleo89/Arcturus-Morningstar-Extended`. +- [ ] Open ready-for-review PR to `duckietm/Arcturus-Morningstar-Extended:dev`. diff --git a/docs/superpowers/specs/2026-06-15-earnings-center-design.md b/docs/superpowers/specs/2026-06-15-earnings-center-design.md new file mode 100644 index 00000000..1f758680 --- /dev/null +++ b/docs/superpowers/specs/2026-06-15-earnings-center-design.md @@ -0,0 +1,97 @@ +# Earnings Center Design + +## Goal + +Add an emulator-owned rewards hub for the "Guadagni" UI. The client and renderer may decide how it looks, but the emulator must own reward amounts, claim eligibility, cooldowns, and anti-abuse checks. + +## Scope + +The first emulator version exposes ten earnings categories: + +- `daily_gift` +- `games` +- `achievements` +- `marketplace` +- `hc_payday` +- `level_progress` +- `donations` +- `bonus_bag` +- `mystery_boxes` +- `club_job` + +Every category can be enabled, disabled, configured with one or more reward currencies, and claimed through a single-row claim or a claim-all request. Categories that are not yet backed by a native hotel subsystem still work through static configuration, so the UI contract is stable while deeper integrations are added later. + +## Architecture + +Add a focused `com.eu.habbo.habbohotel.earnings` package: + +- `EarningsCenterManager` loads category definitions from emulator settings, builds per-user state, and performs claims. +- `EarningsCategory` is the allowlisted category enum and carries the client key. +- `EarningsReward` represents one configured reward. +- `EarningsEntry` is the serializable row state sent to the client. +- `EarningsClaimResult` reports single/all claim outcomes. + +The packet layer only parses category keys and delegates to the manager. The client never sends amounts, cooldowns, or reward definitions. + +## Persistence + +Add a database update that creates `users_earnings_claims`: + +- `id` +- `user_id` +- `category` +- `period_key` +- `claimed_at` +- unique key on `user_id`, `category`, `period_key` + +The unique key is the main double-claim guard. `period_key` is calculated by the emulator from the category cooldown. Daily-style rewards use the UTC date key by default. One-time or long cooldown rows can use the cooldown bucket derived from `claimed_at`. + +## Configuration + +Add emulator settings with safe defaults: + +- `earnings.enabled=0` +- `earnings..enabled=1` +- `earnings..cooldown.seconds=86400` +- `earnings..credits=0` +- `earnings..pixels=0` +- `earnings..points=0` +- `earnings..points.type=5` + +The feature defaults off so existing hotels do not receive surprise economy changes after deploying the jar. + +## Packet Contract + +Add three incoming handlers: + +- `RequestEarningsCenterEvent` +- `ClaimEarningsRewardEvent` +- `ClaimAllEarningsRewardsEvent` + +Add two outgoing composers: + +- `EarningsCenterComposer` +- `EarningsClaimResultComposer` + +Composer format is intentionally simple and renderer-friendly: category key, enabled state, claimable state, next claim timestamp, rewards, and result code. Header IDs must be wired through `messages.ini`/packet registration in the same style as the rest of the emulator. If the renderer side chooses final IDs later, only the packet mapping should need adjustment. + +## Security + +- Reject unknown category keys. +- Reject all claims when `earnings.enabled=0`. +- Never trust reward amounts from the client. +- Clamp configured rewards to non-negative values. +- Use the database unique key to prevent concurrent double claims. +- `claim all` processes only claimable rows and returns per-category results. + +## Tests + +Add unit tests around the manager-level logic: + +- disabled global feature returns disabled rows and rejects claims +- unknown category is rejected +- successful claim grants configured currency once +- duplicate claim in the same period is rejected +- claim-all grants all claimable rows and skips already claimed rows + +Packet tests can remain light because renderer IDs may be finalized separately; the critical behavior is the server-side claim guard.