diff options
Diffstat (limited to 'internal/game/casino.go')
| -rw-r--r-- | internal/game/casino.go | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/internal/game/casino.go b/internal/game/casino.go index f9eb771..79d324a 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -103,16 +103,28 @@ func (w casinoWallet) payCreditsFlagged(amount int, refund bool) error { // resort: pay through the character file only. The save below is // the commit point — the money is durable even without a journal // record, so the settlement may be announced as paid. The stake - // resolution evidence (ResolveStakes) keeps recovery from treating - // the round as unresolved; without a payout record, an open wager - // can no longer be distinguished from a lost one, so the balance - // itself is the only record of what happened. + // resolution evidence (recordStakeEvidence) recorded in that same + // file keeps recovery from treating the round as unresolved; + // without a payout record, an open wager can no longer be + // distinguished from a lost one, so the balance itself is the only + // record of what happened. if capErr != nil { return capErr } w.p.Credits = creditsAfter + // The character file is the only durable record, so it must also + // carry the resolution evidence for this player's open stakes: a + // crash before the games' own ResolveStakes call would otherwise + // leave the wager records open with checkpoint balances that no + // longer match, and recovery would refund chip stakes the paid + // settlement had already consumed. The single save below is the + // commit point for the payout AND the resolution. + resolved := w.recordStakeEvidence() if serr := w.g.AccountStore.SaveCharacter(w.p); serr != nil { w.p.Credits = creditsBefore + if resolved > 0 { + w.p.ResolvedStakes = w.p.ResolvedStakes[:len(w.p.ResolvedStakes)-resolved] + } return casino.ErrWalletPersistence } kind := "settlement" @@ -174,6 +186,23 @@ func (w casinoWallet) ResolveStakes() { } } +// recordStakeEvidence adds every currently open stake of the player to the +// file-side resolution evidence list and returns how many IDs were newly +// recorded. Used when the economy journal is unavailable: the open wager +// record IDs in the character file prove the round resolved even though no +// settled marker (or payout record) could ever be journaled. The caller +// must persist the character file for the evidence to count. +func (w casinoWallet) recordStakeEvidence() int { + added := 0 + for _, rec := range w.g.Economy.openStakes(economyKey(w.p)) { + if !resolvedStakeRecorded(w.p, rec.ID) { + w.p.ResolvedStakes = append(w.p.ResolvedStakes, rec.ID) + added++ + } + } + return added +} + // RefundOutstanding returns every outstanding stake to the player: chips // come back as chips, credits through the durable payout path. The stakes // are resolved only once the return is durable; on failure the chip return |
