aboutsummaryrefslogtreecommitdiff
path: root/internal/world/world.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-10-05 17:05:14 -0400
committerhistoria <[not public]>2026-10-05 17:05:14 -0400
commite42952469dadfb3535633c66c881050ac128703c (patch)
treea78f7396b72cdbd6fa4f6c454c830f40cf2ad0cb /internal/world/world.go
parent90ad8c0c33b519d5830c69d4128bdc984b5e9de8 (diff)
downloadthehouseoficarus-e42952469dadfb3535633c66c881050ac128703c.tar.gz
fix: gather verbs, walk oom, admin path bypass, roulette refund
Diffstat (limited to 'internal/world/world.go')
-rw-r--r--internal/world/world.go55
1 files changed, 17 insertions, 38 deletions
diff --git a/internal/world/world.go b/internal/world/world.go
index 10ceb08..c9e1559 100644
--- a/internal/world/world.go
+++ b/internal/world/world.go
@@ -6,7 +6,6 @@ import (
"math"
"os"
"path/filepath"
- "strconv"
"strings"
"sync"
@@ -252,46 +251,26 @@ func (w *World) RekeyRooms(idMap map[int]int) {
for newID := range movedSeeded {
w.seeded[newID] = true
}
- type objKeyMove struct {
- oldKey, newKey string
- st *ObjState
- newID int
- }
- var moves []objKeyMove
- for k, st := range w.objStates {
- roomStr, _, ok := strings.Cut(k, ":")
- if !ok {
- continue
- }
- roomID, err := strconv.Atoi(roomStr)
- if err != nil {
- continue
- }
- newID, ok := idMap[roomID]
- if !ok || newID == roomID {
- continue
+ // Rebuild the object-state map from every state, not only states whose
+ // current-room key is in idMap. An object away from its home room is keyed
+ // by the current room, so keying the walk on the map key leaves its
+ // HomeRoomID and WanderRooms stale; a later entry to the renamed home then
+ // fails homeObjStateLocked and creates a duplicate instance. Rebuilding the
+ // map also preserves the invariant mapKey == ObjStateKey(st.RoomID, ...).
+ rekeyed := make(map[string]*ObjState, len(w.objStates))
+ for _, st := range w.objStates {
+ if newID, ok := idMap[st.RoomID]; ok && newID != st.RoomID {
+ st.RoomID = newID
}
- newKey := fmt.Sprintf("%d:%s", newID, k[len(roomStr)+1:])
- moves = append(moves, objKeyMove{k, newKey, st, newID})
- }
- for _, m := range moves {
- delete(w.objStates, m.oldKey)
- }
- for _, m := range moves {
- // Keep the package invariant mapKey == ObjStateKey(st.RoomID, ...):
- // object lookups filter on st.RoomID while GetObjState looks up the
- // key, so a rekey that leaves RoomID stale makes the object vanish
- // from the renamed room (and TickObjWander then creates a second
- // entry for the same state). Remap wander rooms like MobStore does.
- m.st.RoomID = m.newID
- if mapped, ok := idMap[m.st.HomeRoomID]; ok && mapped != m.st.HomeRoomID {
- m.st.HomeRoomID = mapped
+ if newID, ok := idMap[st.HomeRoomID]; ok && newID != st.HomeRoomID {
+ st.HomeRoomID = newID
}
- for i, room := range m.st.WanderRooms {
- if mapped, ok := idMap[room]; ok && mapped != room {
- m.st.WanderRooms[i] = mapped
+ for i, room := range st.WanderRooms {
+ if newID, ok := idMap[room]; ok && newID != room {
+ st.WanderRooms[i] = newID
}
}
- w.objStates[m.newKey] = m.st
+ rekeyed[w.ObjStateKey(st.RoomID, st.DefID, st.Index)] = st
}
+ w.objStates = rekeyed
}