aboutsummaryrefslogtreecommitdiff
path: root/internal/game/exit_migrate.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-15 15:35:52 -0400
committerhistoria <[not public]>2026-09-15 15:35:52 -0400
commit0b0b25222b3131ada79ff78c28eb8bf07d977deb (patch)
tree2ceaef5203595044f66a8f00064cd8e017f8f48d /internal/game/exit_migrate.go
parent396c3facb8287b9a34076cae8f3d7b300d366d99 (diff)
downloadthehouseoficarus-0b0b25222b3131ada79ff78c28eb8bf07d977deb.tar.gz
feat: single-owner game state, transactional lifecycle, durable money on server stop
Diffstat (limited to 'internal/game/exit_migrate.go')
-rw-r--r--internal/game/exit_migrate.go39
1 files changed, 35 insertions, 4 deletions
diff --git a/internal/game/exit_migrate.go b/internal/game/exit_migrate.go
index ff905f6..db70c8d 100644
--- a/internal/game/exit_migrate.go
+++ b/internal/game/exit_migrate.go
@@ -112,11 +112,11 @@ func rekeyIntMap[V any](m map[int]V, idMap map[int]int) bool {
return true
}
-// RewriteRoomIDs is the shared entry point called by every room-ID change path
-// (the swapid command and the admin web GUI rename) to migrate room-ID-embedded
+// RewriteRoomIDs is the shared entry point called by every room-ID change
+// path (the swapid command and the admin web GUI rename) to migrate room-ID-embedded
// state across all characters. Online players are updated in memory (and
-// re-saved); offline characters are loaded, rewritten, and saved. It follows
-// the same cross-goroutine mutation precedent as cmd_undig/cmd_summon.
+// re-saved); offline characters are loaded, rewritten, and saved. Callers
+// must be on the owner goroutine (use MigrateRoomIDs from other goroutines).
func (g *Game) RewriteRoomIDs(idMap map[int]int) {
if len(idMap) == 0 {
return
@@ -150,3 +150,34 @@ func (g *Game) RewriteRoomIDs(idMap map[int]int) {
}
}
}
+
+// MigrateRoomIDs is the complete room-ID migration entry point for other
+// goroutines (the admin API and swapid command): player state, Hub room
+// buckets, casino room keys, world room-keyed runtime state, and live mob
+// instances all move together under one owner task. This is what makes a
+// live rename leave NO gameplay or broadcast attached to the old location.
+func (g *Game) MigrateRoomIDs(idMap map[int]int) {
+ if len(idMap) == 0 {
+ return
+ }
+ g.RunOnOwner(func() {
+ g.migrateRoomIDsLocked(idMap)
+ })
+}
+
+// migrateRoomIDsLocked performs the full runtime migration; caller must
+// already be on the owner goroutine.
+func (g *Game) migrateRoomIDsLocked(idMap map[int]int) {
+ if g.Hub != nil {
+ g.Hub.RekeyRooms(idMap)
+ }
+ if g.Casino != nil {
+ g.Casino.RekeyRooms(idMap)
+ }
+ g.World.RekeyRooms(idMap)
+ g.MobStore.RekeyRooms(idMap)
+ // The file paths changed under the world: rebuild its room index so
+ // lookups agree with the post-migration layout.
+ g.World.RebuildRoomIndex(g.DataDir)
+ g.RewriteRoomIDs(idMap)
+}