Commit Graph
91 Commits
Author SHA1 Message Date
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 0f68eec26b feat: real-time multiplayer race mode (free, prestige, crypto)
Adds a complete block-cadence multiplayer race mode alongside solo and tavern.
  Disabled by default; enable with MATCH_ENABLED=true.

  Highlights:
  - New shared engine: MatchRoom, MatchEngine, MatchState (transport-agnostic, unit-tested).
  - Per-economy queues: free, credits_prestige, crypto_race with atomic escrow/refund.
  - MatchScheduler drains queues on every new block and starts 2–32 player races.
  - MatchManager handles Socket.IO lifecycle, server-authoritative movement, reconnect grace,
    forfeit/AFK handling, and end-of-match persistence.
  - Crypto races use race-entry tickets (grants.race_entries) to avoid on-chain refunds; winner
    payout is queued through the existing batch payout/retry service.
  - Leaderboard integration: free → Pleb, prestige → /api/leaderboard?board=prestige,
    crypto → Hall of Champions.
  - Tavern integration: Queue for Race panel, active race list, and live spectator rendering.
  - Dedicated /match.html client with economy selector, race HUD, and post-match scoreboard.
  - Migration 022 adds matches, match_entrants, match_events, match_queue_entries,
    race_entry_transactions, users.race_entries, and payouts.match_id.

  Docs:
  - New docs/MATCH_MODE.md with full architecture, config, events, and operational notes.
  - Updated README.md, docs/TAVERN_AND_MULTIPLAYER.md, docs/TODO.md, src/.env.example,
    and src/.env.

  Tests: 40 new unit tests across 7 suites, all passing.

  Known follow-ups for real-world validation:
  - Full integration test with Postgres + Socket.IO.
  - Server boot check with MATCH_ENABLED=false (default) to ensure solo/tavern remain unaffected.
  - Browser render-kit verification in /match.html and tavern spectator.
  - Crypto-race payout end-to-end with real wallet-rpc.
2026-07-09 13:26:52 -04:00
jwinterm 8fa8b06b20 feat: lively tavern (NPCs + speech bubbles), spectator camera, dungeon render adapter
- tavernLife.js: client-side NPCs (bartender, patrons, cat) with autonomous
    movement, random speech bubbles, and real-player chat bubbles
  - T2b: spectator camera — watch live dungeon runs from inside the tavern
    (game list, spectate_start/update, ESC to leave)
  - R1: sceneFromGameState adapter — converts dungeon game state to render-kit
    Scene with lighting grid and entity mapping
  - R2: pre-populated Kenney roguelikeSheet tile defaults for the tiled renderer
  - Dungeon renderer support: TileRenderer + AsciiRenderer handle lightGrid,
    dungeon features/items/monster entities
  - 3 new tests (242 total, 36 suites, all passing)
2026-07-09 06:31:35 -04:00
jwinterm 4ee03f24a6 fix: char customizer flakiness + wire real render-mode entitlement gating
- Equipment option tiles register for async redraw (were stuck on '...')
  - Render mode switching no longer silently mutates avatar identity
  - Dungeon renderer falls back to @ tile when overlay draw fails
  - Main-game customizer locked to topdown (no confusing render-mode picker)
  - equipRedrawers prevents unbounded redraw array growth
  - RENDER_MODE_TEST_UNLOCKS flipped to false; ASCII made free (accessible fallback)
  - Documented COSMETIC_PRODUCTS in .env.example
  - 5 new tests (239 total, 36 suites, all passing)
2026-07-09 06:15:00 -04:00
jwinterm fa18e99a94 correct iso avatar customization 2026-07-06 07:26:12 -04:00
jwinterm 49ea01606e fix designed-room iso character rendering 2026-07-06 07:04:26 -04:00
jwinterm f505a4fb8a make character customization projection aware 2026-07-06 06:38:19 -04:00
jwinterm c89c01e5f1 improve gear tinting and unlock render tests 2026-07-06 04:38:28 -04:00
jwinterm 83020f6c08 polish character customizer render choices 2026-07-06 04:26:00 -04:00
jwinterm 1ca18dfdbc fix: render visible animated 3d tavern avatars 2026-07-06 04:11:43 -04:00
jwinterm cb9efbe66c refactor: route render packs through avatar visuals 2026-07-06 03:53:13 -04:00
jwinterm 3195386ba1 refactor: resolve avatar visuals through render kit 2026-07-06 03:41:11 -04:00
jwinterm be780c17e6 feat: use character identity in single player 2026-07-06 03:16:26 -04:00
jwinterm 07cfe80591 feat: improve character customization colors 2026-07-05 21:09:52 -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 038f47051f mobile: compact action buttons to one row, shrink/lighten D-pad
On phones the primary buttons now read START / WATCH / SHOP (short labels via
spans toggled by media query) with tighter padding so they fit a single row.
The on-screen D-pad is smaller (44px) and more transparent so it covers less
of the chat/game underneath.
2026-06-01 08:35:33 -04:00
jwinterm f9e658e841 mobile: make play area fill screen width
On phones the dungeon canvas was letterboxed: the game grid row was 1fr and
got squeezed by the status bar + chat, so the 800x608 canvas scaled to that
short height and rendered narrow with black side bars.

Drive the game area by width instead — full-width box with the canvas's own
aspect ratio (auto height) — and hand the leftover vertical space to chat
(now 1fr, max-height cap removed) so it's roomier too.
2026-06-01 08:32:06 -04:00
jwinterm bfca9b340f feat(mobile): viewport, responsive layout, and touch controls
The layout was already partly responsive (max-width:100vw, min(480px,90vw)
modals, canvas max-width:100%, and the renderer centres a fixed viewport on the
player) but had no viewport meta, so none of it engaged on phones.

- Add the viewport (+charset) meta — unlocks the existing responsive rules.
- Mobile media query (<=820px): stack the 3-column grid into one column
  (header/status/game/chat/input/footer), shrink fonts, and cap the fixed-width
  play/history/leaderboard modals to 94vw so they fit instead of overflowing.
- On-screen D-pad + swipe-to-move (new touchControls.js), both emitting the
  same player_move {direction} event the keyboard uses — no game-logic change.
  Shown on small screens or any touch device (body.touch).
- Remove the leftover "GAME AREA" debug overlay.
2026-05-31 16:13:21 -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 7581ba79cb refactor: frontend de-spaghetti (dup declares, dead code, log gating)
- Remove the duplicate _gameMode declaration in the client SocketHandlers
  object literal — it was declared twice, so the later `null` silently
  shadowed the earlier `'free'`. Now declared once with the effective value.
- Remove the dead SocketHandlers._appendMessage calls in smirkAuth.js; that
  method never existed, so the guard always fell through to the working
  .text() append. Keep the safe append.
- Gate broadcastManager's high-volume per-event logs (user count, chat message
  incl. message/socketId PII, game update, game start) behind debug mode;
  previously they logged on every event regardless of NODE_ENV.

Full suite: 21 suites / 155 tests.
2026-05-31 14:39:12 -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 223aa75871 security: move session token to handshake auth and rotate on resume
The anonymous session token is a bearer credential that was sent in the
Socket.IO handshake query string, where it leaks into proxy/access/referer
logs and is easily observed. Anyone holding it becomes that user (credits,
payout address, pending payments).

- Client now sends the token in the handshake `auth` payload instead of the
  query string. Server reads `auth` first and falls back to the query string
  for backward compatibility during rollout.
- The token is rotated on every successful resume, so a leaked/observed
  token is invalidated the next time the legitimate owner reconnects. The
  client already persists the token returned in `session_resumed`.

Adds a security test asserting resume returns a new token and the old token
no longer resumes. Full suite: 12 suites / 116 tests.
2026-05-31 09:29:20 -04:00
jwinterm 82fdcc0203 update sockethandlers 2026-04-18 19:11:22 -04:00
jwinterm f2b107fc5f fix stale smirk and amount bug 2026-03-01 13:56:35 -05: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 1a714fd69d fix credits display 2026-02-20 09:36:55 -05:00
jwinterm ee5a037b84 fix credits logic 2026-02-20 09:21:13 -05:00
jwinterm bc55f0355e fix edge cases and tests 2026-02-19 06:15:45 -05:00
jwinterm 727304996a fix live game list and swap animations 2026-02-18 20:57:01 -05:00
jwinterm 6860debe9a fix admin balance display 2026-02-18 19:20:00 -05:00
jwinterm bf5938c366 fix game entry and payout bugs 2026-02-18 06:35:32 -05:00
jwinterm d56ad7599b fix admin balance display 2026-02-17 20:21:32 -05:00
jwinterm 320d1a3b1f fix admin panel and credits package 2026-02-17 20:02:22 -05:00
jwinterm a56063867e fix: chat scrollback and admin control 2026-02-03 12:02:52 -05:00
jwinterm 10dfd932d8 fix smirk auth 2026-02-02 17:17:10 -05:00
jwinterm 6cf3961da0 feat: add smirk toggle and more admin capabilities 2026-02-02 08:42:39 -05:00
jwinterm d27df3b6cf Feat: add IP-based rate limiting and house balance thresholds 2026-02-01 17:38:30 -05:00
jwinterm 6e0f3e9012 fix: wallet display bug, add test email endpoint
- Fix wallet balance always showing 'Disconnected' in admin dashboard
- Always attempt balance fetch even if isHealthy=false
- Show error state with message instead of generic 'Disconnected'
- Add POST /api/admin/alerts/test-email endpoint to verify Resend config
- Move alertService to module scope for endpoint access
2026-02-01 15:59:30 -05:00
jwinterm a81c19c936 feat: admin dashboard, alert service, and docs reorganization
- Add alertService.js with Resend email alerts for low balance, disconnects, failed payouts
- Update admin.html with full dashboard UI (stats, charts, tables, payout retry)
- Add wallet balance to /health endpoint
- Add getBalance() and checkTransactionStatus() to walletRPCService
- Fix payoutRetryService query and add alert integration
- Update .env.example with alert config (RESEND_API_KEY, ADMIN_EMAIL, etc)
- Reorganize docs: move TODO.md, LOGS_AND_BACKUP.md to docs/
- Extract deployment guide from README to docs/DEPLOY.md
- Consolidate TEMP_TODO.md into docs/TODO.md
2026-01-31 20:21:28 -05:00
jwinterm 7573c300cd fix: smirk modal 2026-01-29 08:46:52 -05:00
jwinterm 2286d8deff Feat: add smirk login
Fix: add security hardening and transaction database commits
2026-01-28 17:21:53 -05:00
jwinterm 8fb5c58f9a Fix: History payments 2026-01-13 19:13:11 -05:00
jwinterm 37323c8683 fix: monster animation p3 2026-01-13 18:37:40 -05:00
jwinterm 12bc3d73d0 fix: monster animation p2 2026-01-13 18:09:04 -05:00
jwinterm 7bd32a929e fix: monster animation in awaiting payment 2026-01-13 18:04:32 -05:00
jwinterm 0c2d44d429 fix: Animation rendering issues - remove black tile backgrounds
- Replace asterisk (*) sparkles with floor tiles + bright golden color
- Remove skull emoji (☠) and death particles (% *) - use red flash effect
- Fix monster shadows causing black boxes - use red floor glow instead
- Replace 'ESCAPED!' emoji text with character-by-character transparent rendering
- Use GameTiles.getPlayerTile() instead of hardcoded '@'
- Use GameTiles.getMonsterTile() instead of hardcoded '~'

All tiles now render with proper transparency on floor tile base.
2026-01-13 17:32:46 -05:00