From cc33072eced3d5460512c09c42ec4531c807d7af Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sat, 19 Sep 2026 01:55:34 -0400 Subject: fix: casino stake preservation, world state reconciliation, casino game registration --- internal/casino/core.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'internal/casino/core.go') diff --git a/internal/casino/core.go b/internal/casino/core.go index 7ac728f..0b9d0af 100644 --- a/internal/casino/core.go +++ b/internal/casino/core.go @@ -105,10 +105,17 @@ func (c *tableCore[P]) advanceBettingLocked(resolve func() []Event, reset func() // refundAllLocked refunds every committed wager through its wallet exactly // once and returns the events. The caller resets its own round state // afterwards, so a refunded round can never settle and pay again. +// +// It deliberately does NOT gate on p.HasBet: a stake whose payout could not +// be persisted stays pending after resetRound clears HasBet, and a shutdown +// or room eviction must still return it. RefundOutstanding is the player-wide +// ledger and a player can only participate in one casino game at a time, so +// refunding every seated wallet is safe and returns exactly that player's +// outstanding stakes. func (c *tableCore[P]) refundAllLocked() []Event { var events []Event for _, p := range c.players.participants() { - if !p.HasBet || p.Wallet == nil { + if p.Wallet == nil { continue } name := p.Name @@ -127,6 +134,22 @@ func (c *tableCore[P]) refundAllLocked() []Event { return events } +// resolveStakeIDs consumes each listed pending stake by wallet handle. It is +// the per-handle counterpart to ResolveStakes: use it whenever another stake +// may still be pending for the same player (for example an earlier payout +// that failed to persist), so consuming one round's stakes cannot destroy an +// unrelated refundable stake. +func resolveStakeIDs(w Wallet, ids []string) { + if w == nil { + return + } + for _, id := range ids { + if id != "" { + w.ResolveStake(id) + } + } +} + // settleStakeOutcome applies one wager's outcome through the wallet and // reports whether the settlement could NOT be made durable. It carries the // money-critical ordering shared by every table game (documented in -- cgit v1.2.3