Commit Graph
31 Commits
Author SHA1 Message Date
jwinterm d925df1ae9 feat(render): re-enable render-kit SP dungeon with player-centered camera + goblin monster
Commit to the render kit as THE single-player renderer (legacy = hard fallback only). Fixes
the two things that broke it:
- CAMERA: each renderer now exposes focusPoint (the player's pixel pos); the SP bridge mounts
  a self-sizing 16:10 viewport host and CSS-transforms the canvas to centre the player at a
  readable zoom (wheel to zoom). Renderer-agnostic (tiled/iso/3d). No more whole-level-in-a-corner.
- MONSTER: the tiled renderer drew a hardcoded red dot; now it draws the Goblin character sprite
  (char-goblin, the same path the tavern draws characters), red orb only as last-resort fallback.
Re-enabled: _drawGameScreen prefers RK.SPGame; spRenderPicker ENABLED. Suite 62/435 green.

NEXT (still owed): make the splash + both waiting animations render through the kit too, so
they use the chosen pack/mode instead of the ROT text screens.
2026-07-12 10:56:14 -04:00
jwinterm cc0e092c1d fix(sp): revert dungeon to legacy renderer + fix splash (working game restored)
The render-kit SP dungeon shipped without a player-centered camera or entity sprites,
so it drew the whole level tiny in a corner with a red-dot monster. Disable it and fall
back to the proven legacy renderer (original tiles, real monster, centered view) until
the kit has a camera + sprites. RK.SPGame/spRenderPicker kept but dormant (one flag to
re-enable). Splash legend: draw every icon (incl. the player) as a uniform grid tile —
no avatar overlay — so the four rows align AND the player shows the original hero tile.
2026-07-12 10:30:19 -04:00
jwinterm 1325b49b42 feat(render): single-player dungeon renders through the render kit (packs in gameplay)
The migration that makes the pack ladder pay off IN the dungeon, not just the tavern.
The SP game now draws via RK (Tiled/ASCII/Iso/3D + unlocked packs) instead of the
legacy ROT display.

- Adapter: sceneFromGameState now consumes the CLIENT state shape (sparse {y:{x:v}}
  tile maps, not just server arrays) via maxDims(). Verified + unit-tested.
- Bug fix: RK.sceneFromGameState was never actually exposed (only RK.scene.*), so
  matchClient + tavern spectator were silently no-op-ing. Aliased onto RK.
- Bridge (spGameRenderer.js, RK.SPGame): mounts an RK renderer in a dedicated host
  inside #game-display, toggles the legacy ROT canvases, zoom-enabled. Game._draw
  GameScreen prefers it and FALLS BACK to RenderEngine on any failure, so the live
  game can never blank. ROT still draws the splash/win/lose text screens.
- Picker (spRenderPicker.js): homepage mode + pack selector, gated by entitlements
  (free = Tiled/Original + ASCII; ladder unlocks Iso/3D/packs), rebuilds on identity.
- index.html loads the render-kit renderers + the bridge/picker.

Bundled with the catalog ladder (migration 028): free Original bare pack, ladder
1/5/10/20/40/50. Deploying makes the free tavern bare (by design) AND the dungeon
render-kit-ed. v1 renders the whole explored level + zoom (player-centered camera is
the next polish). Suite 62/435 green; adapter smoke-verified.
2026-07-12 10:14:56 -04:00
jwinterm 6c7a677057 feat(ui): buy modal frames direct entry as '1 credit' + payout-honest
The single-game option now reads 'Single game · 1 credit' and notes it counts toward cosmetic unlocks (matching the backend: a direct entry advances total_credits_purchased). Fixes the direct payout copy to only show multipliers when payouts are actually enabled (was defaulting on).
2026-07-10 16:29:27 -04:00
jwinterm b31a408789 feat(ui): consolidate help to a single credits model; make reward line payout-honest
Reframe the two 'Direct Payment / Credits Mode' cards as one 'Credits' model — 1 credit = 1 run, bought singly at base price or in discounted bundles. Adds the drop-in-timing note (jump in now or next block; block timing is memoryless so the expected wait is the same). Reward line is now config-driven: shows crypto multipliers only when payouts are actually enabled, otherwise the Hall-of-Champions framing — fixes the help advertising 2x/3x payouts on a PAYOUTS_ENABLED=false (prestige) deployment. Header renamed to 'Credits & Entry'.
2026-07-10 14:53:50 -04:00
jwinterm a243dd8fc6 fix(ui): real right gutter so play-area focus outline shows on the right; Smirk flow
Play area: add a 6px right gutter on .container (border-box) so the outward yellow focus outline isn't clipped by overflow:hidden at the viewport edge — the inset-outline attempt got clipped in Chromium. Revert to an outward outline (ui.js).

Smirk: on the NIP-98 path, only fall back to the legacy connect() when the wallet genuinely lacks signNostrEvent — a LOCKED or user-cancelled signNostrEvent now surfaces instead of triggering a second unlock prompt. (The unlock-popup-on-locked behavior itself is a wallet-build capability, added to smirk-monorepo 2026-07-09; builds before that throw LOCKED and get the friendly retry hint.)
2026-07-10 09:11:07 -04:00
jwinterm a05a10efd7 fix(ui): tavern floor, play-area focus border, and Smirk locked-wallet UX
Tavern: revert the per-cell 'varied floor/wall' tiles to coherent single tiles — mixing wood/stone/plank per cell read as visual noise (assetPacks.js).

Play area: draw the keyboard-focus outline inset (outline-offset -2px) so the yellow border shows on the right edge, which the container's overflow:hidden was clipping (ui.js).

Smirk: a locked wallet now shows a friendly 'unlock in the extension, then Retry' hint instead of a red error, and the LOCKED error code is preserved through connect()/signMessage(). Current Smirk builds auto-open the unlock popup on connect(); older builds throw LOCKED, which the Retry button re-invokes (smirkAuth.js).
2026-07-10 08:46:38 -04:00
jwinterm a62eefb47b fix: resolve security/correctness review + AAA graphics pass
Backend (Tier 0/1/3): single-payout double-pay -> needs_review; admin-retry tx_hash guard; UNIQUE index on games.payment_id (migration 023) + atomic claim; reconnect no longer resets block-timeout; completeGame keys on user_id+dungeon_seed (not socket_id); token-gated /api/user/:socketId/* endpoints; payout min/max enforcement; orphaned-active-game boot recovery; sessionManager cleanup FK fix; XFF rightmost-hop; global uncaughtException/unhandledRejection guard; server binds 127.0.0.1; provably-fair client-seed (HMAC) + RNG [0,1) bound; difficulty preset ranges reach the digger; chat no longer leaks full socket.id; removed dangerous-keyword SQL theater.

Match mode (Tier 2, still MATCH_ENABLED-gated): fixed match_queue/match_move crash paths + scheduler dead-code + leaked ceiling timer; pot collected before start with abort+refund; BigInt/basis-point fee math, capped payout; no-address winner claimable; winnerId==placement[0]; finalize schema + payout-first isolation; reconnect re-key with ownership; refunds on all cancel paths; real countdown; map/timer cleanup. +16 tests.

Graphics: new overlay FX layer (torch light, vignette, embers, sparkle/burst/flash/shake, self-suspending rAF); gameplay juice; atmospheric screens; CSS design-token chrome with framed modals; richer Kenney tile renderer; imported Kenney dungeon/interior sheets + fx particles.

Verification: 45 suites / 312 tests pass; 40 changed JS files parse; 20 server modules load clean; no regressions.
2026-07-09 17:46:58 -04:00
jwinterm 454e6ab69a feat: add tavern render kit and character entitlements 2026-07-05 20:57:46 -04:00
jwinterm 63e3006aca launch features: win feed, public stats, share-a-win, live CTA
Four pre-launch additions to make the game feel alive and shareable:

- Live win feed: server broadcasts 'win_feed' on every escape; client shows a
  transient toast ('X escaped with the bag') so the room feels active.
- Public stats: GET /api/stats (10s-cached) returns games + escapes in the last
  24h and total paid out; a status-area strip polls it for social proof.
- Share-a-win: game-over screen gets 'Share to X' + 'Copy link' buttons pointing
  at the /verify page, which now renders OpenGraph/Twitter-card meta (brand OG
  image per instance) so shared links unfurl with a preview.
- Land-on-action: a dismissible 'N games live now — watch' CTA appears on connect
  when games are in progress, opening the existing spectator panel. Non-intrusive:
  hidden while playing/spectating and never hijacks the canvas.
2026-06-01 09:17:48 -04:00
jwinterm e6936f47d9 feat: network-aware currency label (sXMR), game name, and Smirk gating
- Currency display is now network-aware: XMR on a test network shows sXMR
  (stagenet) / tXMR (testnet) so it's clear the coins aren't mainnet; mainnet
  XMR shows XMR, Wownero stays WOW. A fork running mainnet automatically shows
  XMR. cryptoType (used for decimals/QR asset) is unchanged.
- Product name (Monerogue/Wownerogue) is derived from the currency and no
  longer hardcoded: the chat "Connected to <name> server" message, payment
  descriptions, and the verify page title all follow it.
- Smirk is forced off on any test network (stagenet/testnet) regardless of
  SMIRK_ENABLED, since Smirk only works on mainnet — so forks don't have to
  remember the env flag.

New shared helpers (gameNameFor, currencyLabelFor, isTestNetworkFor); exposed
via game_mode_info (currencyLabel, gameName). Full suite: 22 suites / 159 tests.
2026-05-31 15:57:59 -04:00
jwinterm ccdb4521b2 feat(ui): crypto-aware title/favicon + clearer Champions vs Pleb framing
- Footer title and favicon now track the currency: "Monero Roguelike" + the
  Monero logo favicon on the XMR instance, "Wownero Roguelike" + the existing
  favicon on WOW (driven by UI.updateGameTitle).
- "Choose How to Play" modal: a header explains that paying (credits/entry)
  puts high scores in the Hall of Champions while free play uses the Pleb
  leaderboard, and each option now says which board it feeds — on both the
  no-payout (mainnet) and payout (stagenet) variants.
2026-05-31 15:40:26 -04:00
jwinterm 988617289b feat: free-play + dual-leaderboard frontend
- Leaderboard panel: two boards via tabs — 🏅 Hall of Champions (paid) and
  🪙 Pleb (free) — default Champions; passes board= to /api/leaderboard and
  retitles per board.
- PaymentUI: the Free button now shows whenever free play is offered (instance
  free-only OR free-as-a-choice via freePlayEnabled), labelled "Play Free / no
  payout / Pleb leaderboard" on paid instances, and emits the play_free event
  (records game_mode=FREE). Replaces an emit of the dead 'enter_game' event.
- Server game_mode_info payload now includes freePlayEnabled so the client can
  show the choice.

Full suite: 22 suites / 158 tests.
2026-05-31 15:08:54 -04:00
jwinterm a664a8bbce security: escape XSS sinks client-side and add CSP + security headers
The client trusted the server to pre-escape chat content and rendered
user-supplied fields via .html()/innerHTML — one server regression away from
stored XSS, and the admin panel injected user-controlled payout addresses
into its authenticated DOM.

- Add a single shared escapeHtml helper (escapes all five HTML-significant
  chars including both quotes); leaderboard now delegates to it.
- Escape chat username + message in onChatBroadcast/onChatHistory.
- Escape user-controlled fields in the admin panel (payout address, socket
  id, player name, status) and make its local escapeHtml quote-safe so values
  in title="..." can't break out.
- Add CSP plus X-Content-Type-Options, X-Frame-Options and Referrer-Policy
  headers via middleware. connect-src 'self' keeps Socket.IO working;
  removing 'unsafe-inline' (nonces) is tracked as a later cleanup.

Full suite: 13 suites / 119 tests.
2026-05-31 09:40:34 -04:00
jwinterm a61851b0f7 add smirk payments and leaderboard and diff tuning 2026-02-20 13:54:36 -05:00
jwinterm 27660d6948 Fix rewards, make tx hash clickable, add win payout notification, and add entry choice modal 2026-02-20 12:34:21 -05:00
jwinterm 8fb5c58f9a Fix: History payments 2026-01-13 19:13:11 -05:00
jwinterm aec1c71a8c add early entry and help screens for new users 2025-12-26 10:21:25 -05:00
jwinterm 675caf220f fix payment modal 2025-12-24 19:31:46 -05:00
jwinterm e218fbf67b fix payment UI 2025-12-24 17:24:04 -05:00
jwinterm 7d701fe01b add backup scripts and improve docs and .env.example 2025-12-22 16:29:32 -05:00
jwinterm 7f91d83308 fix monster bug and let spectators join pending games 2025-12-22 11:25:22 -05:00
jwinterm aa419689c8 fix multimode payments and get credits working again 2025-12-21 14:08:20 -05:00
jwinterm deca4a4685 add db commands and test payout (worked!) 2025-11-23 13:33:04 -05:00
jwinterm fa61d60bc0 Limit payment requests 2025-09-30 07:03:41 -04:00
jwinterm 4e7a773496 add address modal and try to fix payout 2025-09-29 17:40:59 -04:00
jwinterm 9a4911f410 fix audio and add new audio and fix qr and db index 2025-09-28 10:43:48 -04:00
jwinterm 2d993379bf single_game payment and audio alerts working 2025-09-28 09:23:00 -04:00
jwinterm f8241dd309 Continue working on payment logic 2025-09-27 11:21:11 -04:00
jwinterm e3915dcde2 Begin payment logic and tests 2025-09-27 08:45:22 -04:00
jwinterm f02e16272e refactor frontend and fix debug mode 2025-05-29 13:40:44 -04:00