From 8fe9e3c3fef0049df82281a62afe35dda516dfe2 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 17:48:26 -0400 Subject: fix: close combat ghost, admin traversal, login throttle, journal double-pay, and quality/economy gaps --- internal/game/casino.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'internal/game/casino.go') diff --git a/internal/game/casino.go b/internal/game/casino.go index dcf4273..3e382e9 100644 --- a/internal/game/casino.go +++ b/internal/game/casino.go @@ -1,6 +1,7 @@ package game import ( + "errors" "fmt" "os" "strconv" @@ -11,6 +12,7 @@ import ( "thehouseoficarus/internal/casino" "thehouseoficarus/internal/color" "thehouseoficarus/internal/net" + "thehouseoficarus/internal/persistence" "thehouseoficarus/internal/player" ) @@ -54,6 +56,17 @@ func (w casinoWallet) Wager(amount int) (casino.Wager, error) { } w.p.Credits -= credits if err := w.g.AccountStore.SaveCharacter(w.p); err != nil { + if errors.Is(err, persistence.ErrDurabilityUncertain) { + // The character file was replaced but the directory sync failed: + // the debit may be durable. Keep the in-memory debit and the + // journal record OPEN instead of voiding it, so recovery compares + // checkpoints against whatever file survived and either voids or + // refunds consistently. Proceeding is safe: the record stays open + // (refundable) until the round resolves. + fmt.Fprintf(os.Stderr, "casino wager: %s save durability uncertain: %v — record kept open\n", w.p.Name, err) + w.g.Economy.registerStake(rec) + return casino.Wager{Total: amount, Chips: chips, Credits: credits, ID: rec.ID}, nil + } // Revert the in-memory mutation: the play must not proceed on a // stake that could not be made durable. if chips > 0 { -- cgit v1.2.3