Skip to content

fix: casino 0-balance — persistent guest room for live-roster Credits#73

Merged
BCook98 merged 1 commit into
mainfrom
fix-guest-room-roster
Jul 3, 2026
Merged

fix: casino 0-balance — persistent guest room for live-roster Credits#73
BCook98 merged 1 commit into
mainfrom
fix-guest-room-roster

Conversation

@BCook98

@BCook98 BCook98 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Symptom

Every casino game (blackjack/pokies/scratchies/roulette) shows a 0 balance and refuses all bets in production, despite the platform reserving credits correctly.

Root cause

The guest runtime (internal/game/run.go) builds a fresh room every callback, but creates the game's Handler — and its stored Services (including creditsSvc) — only once at OnStart, bound to the start callback's room. creditsSvc resolves a player's host-side index by scanning that room's ctx.members, which is empty for a solo game (the player joins after OnStart). So creditsSvc.index(p) → -1 and every Balance/Wager/Settle is denied at the guest facade (ErrCreditsDenied) — it never even reaches the host creditsCall.

The kittest/native/memsvc doubles resolve credits by account id, not roster index, so unit tests and shellcade-kit check conformance all passed — the bug only manifests on the real wasm ABI path.

Fix

Use a single persistent theRoom, refreshed in place each callback (its ctx is reassigned in decodeCall), so the game's once-built Services always resolve against the live roster. The room struct is just {ctx, rng} with no per-callback state, and its own comment says it's "refreshed per callback" — this makes that true. No behavior change for non-casino games.

Verification

Reproduced and fixed locally end-to-end (dev server + sideloaded casino blackjack, driven via tmux):

  • Before: BalanceErrCreditsDenied at the facade, HUD shows credits 0, bets refused.
  • After: host creditsCall reached (idx=0 rosterLen=1), Balance1015, HUD shows $1015; placing a bet deals cards and debits to $990.

go build ./... (native + GOOS=wasip1) and go test ./... green.

Follow-ups

  • Casino games must be rebuilt + republished against this release (the fix is compiled into each game's wasm).
  • Add a casino wasm-fixture host test (Start empty → Join → assert a guest credits call reaches the host service) so this can't regress — the current doubles can't catch it.

🤖 Generated with Claude Code

… roster

The guest runtime created a fresh `room` every callback but built the game's
Handler + stored Services only ONCE at OnStart, binding svc.Credits to the
start callback's room. creditsSvc resolves a player's host index against that
room's ctx.members — empty for a solo game (the player joins after start) — so
every Balance/Wager/Settle was denied at the guest facade (ErrCreditsDenied)
and never reached the host: casino games showed a 0 balance and refused bets.

Use a single persistent `theRoom`, refreshed in place each callback, so the
game's once-built Services always resolve against the current ctx. No behavior
change for non-casino games (the room reuse is transparent; ctx is the same
data, just not reallocated).

The kittest/native/memsvc doubles resolve credits by account id rather than
roster index, which is why unit tests and `shellcade-kit check` conformance
missed this — it only manifests on the real wasm ABI path. Follow-up: add a
casino wasm-fixture host test that Start()s empty then Join()s and asserts a
guest credits call reaches the host service.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7oJQSTva5xgbAZomdV5Jj
@BCook98 BCook98 merged commit 8c904b5 into main Jul 3, 2026
6 checks passed
@BCook98 BCook98 deleted the fix-guest-room-roster branch July 3, 2026 10:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant