aboutsummaryrefslogtreecommitdiff
path: root/internal/game/game.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-16 19:57:45 -0400
committerhistoria <[not public]>2026-09-16 19:57:45 -0400
commit6ef40a5739f1723ec26cc32dfc48fe764f776dca (patch)
treee215a4dc96ea639bcea07bb589aae3e31c3609bb /internal/game/game.go
parent1dad15698845d370e998f7cc5feb8aece3fab58f (diff)
downloadthehouseoficarus-6ef40a5739f1723ec26cc32dfc48fe764f776dca.tar.gz
fix: durable payouts survive journal failure, cap bank withdrawals, hash passwords off the owner loop.
Diffstat (limited to 'internal/game/game.go')
-rw-r--r--internal/game/game.go14
1 files changed, 14 insertions, 0 deletions
diff --git a/internal/game/game.go b/internal/game/game.go
index 096e070..7255042 100644
--- a/internal/game/game.go
+++ b/internal/game/game.go
@@ -291,6 +291,20 @@ func (g *Game) HandleSessionOnOwner(sess *net.Session, input string) {
if g.isShuttingDown() {
return
}
+ // Password work is expensive (Argon2id, ~64 MiB and tens of
+ // milliseconds per call) and must never run on the owner goroutine:
+ // the owner serializes every command and tick, so a burst of logins
+ // would stall the whole world. Verify/hash on the caller's connection
+ // goroutine, then submit one owner task for the (cheap) state
+ // transition.
+ switch sess.State {
+ case net.StatePassword:
+ g.handlePasswordOffOwner(sess, input)
+ return
+ case net.StateNewAccount:
+ g.handleNewAccountOffOwner(sess, input)
+ return
+ }
g.RunOnOwner(func() {
// Re-checked at task execution: the flag may flip between
// submission and execution, and RunOnOwner must never fall back