aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_bank.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 05:31:09 -0400
committerhistoria <[not public]>2026-09-18 05:31:09 -0400
commit153acb7f644d755c45533b7c5311e3ffa47e8973 (patch)
tree7645e6f7b65bc3830b078e3b9336d2e6b199d584 /internal/game/cmd_bank.go
parent87d08f0151e643951769e323995f1c5ed89ee200 (diff)
downloadthehouseoficarus-153acb7f644d755c45533b7c5311e3ffa47e8973.tar.gz
fix: harden engine across casino, economy, concurrency, security, and content
Diffstat (limited to 'internal/game/cmd_bank.go')
-rw-r--r--internal/game/cmd_bank.go29
1 files changed, 27 insertions, 2 deletions
diff --git a/internal/game/cmd_bank.go b/internal/game/cmd_bank.go
index 6326700..468b173 100644
--- a/internal/game/cmd_bank.go
+++ b/internal/game/cmd_bank.go
@@ -2,6 +2,7 @@ package game
import (
"fmt"
+ "log"
"sort"
"strconv"
"strings"
@@ -368,9 +369,13 @@ func (g *Game) doBankDepositCredits(sess *net.Session, parts []string) {
sess.WriteLine("You don't have that many credits.")
return
}
+ creditsBefore, bankedBefore := p.Credits, p.BankedCredits
p.Credits -= amount
p.BankedCredits += amount
- g.saveCharacter(p)
+ if !g.persistBankCredits(p, creditsBefore, bankedBefore) {
+ sess.WriteLine("The bank terminal could not record the transfer; nothing was moved.")
+ return
+ }
sess.WriteLine(g.colorize(sess, "currency_pickup", fmt.Sprintf("You deposit %s credits. (Banked: %s)", formatInt(amount), formatInt(p.BankedCredits))))
g.showBankBrowse(sess)
}
@@ -396,13 +401,33 @@ func (g *Game) doBankWithdrawCredits(sess *net.Session, parts []string) {
sess.WriteLine("Your wallet cannot hold that many credits.")
return
}
+ creditsBefore, bankedBefore := p.Credits, p.BankedCredits
p.BankedCredits -= amount
p.Credits += amount
- g.saveCharacter(p)
+ if !g.persistBankCredits(p, creditsBefore, bankedBefore) {
+ sess.WriteLine("The bank terminal could not record the transfer; nothing was moved.")
+ return
+ }
sess.WriteLine(g.colorize(sess, "currency_pickup", fmt.Sprintf("You withdraw %s credits.", formatInt(amount))))
g.showBankBrowse(sess)
}
+// persistBankCredits makes a credit move between the on-hand wallet and the
+// bank durable, reverting it in memory when the save fails. A best-effort
+// save here would leave the in-memory balance ahead of the durable file, and
+// a wager taken from that phantom balance journals checkpoints the file can
+// never match — recovery then leaves the stake permanently ambiguous instead
+// of refunding or settling it. Reports whether the move may be announced.
+func (g *Game) persistBankCredits(p *player.Player, creditsBefore, bankedBefore int) bool {
+ if err := g.AccountStore.SaveCharacter(p); err != nil {
+ log.Printf("bank credit transfer %s: %v", p.Name, err)
+ p.Credits = creditsBefore
+ p.BankedCredits = bankedBefore
+ return false
+ }
+ return true
+}
+
func (g *Game) canUseBank(p *player.Player) bool {
instances := g.World.FindObjInstances(p.RoomID, "bank booth")
return len(instances) > 0