aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_shutdown.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 01:50:17 -0400
committerhistoria <[not public]>2026-09-18 01:50:17 -0400
commit87d08f0151e643951769e323995f1c5ed89ee200 (patch)
treedc42a0b30ebb5a00dd7ba505cc4eaa44f4f308bc /internal/game/cmd_shutdown.go
parent32a3c59cebf2a16277e54d715a67adfdbe00b456 (diff)
downloadthehouseoficarus-87d08f0151e643951769e323995f1c5ed89ee200.tar.gz
fix: harden economy recovery, shutdown concurrency, world validation, and inventory-loss paths
Diffstat (limited to 'internal/game/cmd_shutdown.go')
-rw-r--r--internal/game/cmd_shutdown.go15
1 files changed, 11 insertions, 4 deletions
diff --git a/internal/game/cmd_shutdown.go b/internal/game/cmd_shutdown.go
index 0030649..9a57c6b 100644
--- a/internal/game/cmd_shutdown.go
+++ b/internal/game/cmd_shutdown.go
@@ -105,9 +105,16 @@ func (g *Game) broadcastLoggedIn(msg string) {
if g.Hub == nil {
return
}
- for _, other := range g.Hub.AllSessions() {
- if other.Player != nil {
- other.WriteLine(msg)
+ // Player pointers and option maps are owner-owned. Route the broadcast
+ // through the owner so it cannot race a login/logout or an option change
+ // from a raw shutdown goroutine (a concurrent map read/write would fatal
+ // the process before the final save). Drops harmlessly once the owner has
+ // stopped.
+ g.run(func() {
+ for _, other := range g.Hub.AllSessions() {
+ if other.Player != nil {
+ other.WriteLine(msg)
+ }
}
- }
+ })
}