aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_rooms.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin/api_rooms.go')
-rw-r--r--internal/admin/api_rooms.go50
1 files changed, 29 insertions, 21 deletions
diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go
index 75f4779..124b093 100644
--- a/internal/admin/api_rooms.go
+++ b/internal/admin/api_rooms.go
@@ -821,37 +821,40 @@ func (s *AdminServer) handleRoomRename(w http.ResponseWriter, r *http.Request) {
s.world.RebuildRoomIndex(s.dataDir)
s.world.ClearRoomState(body.ID)
+ // Remap every genuine room-ID reference (exit targets, trigger/on-enter
+ // room+teleport+despawn_rooms, mob wander_rooms) from the old ID to the
+ // new one across all rooms — including the renamed room itself, so a
+ // self-loop exit is corrected too. Only rooms whose references actually
+ // moved are re-marshaled (preserving untouched files' formatting).
+ idMap := map[int]int{body.ID: body.NewID}
allIDs, _ := listRoomIDs(s.dataDir)
- var exitUpdates int
+ var refUpdates int
for _, otherID := range allIDs {
- if otherID == body.NewID {
- continue
- }
otherRoom, loadErr := s.world.LoadRoom(otherID)
if loadErr != nil {
continue
}
- changed := false
- for _, dir := range world.ExitOrder {
- exit, exists := otherRoom.Exits[dir]
- if !exists || exit.Room != body.ID {
- continue
- }
- exit.Room = body.NewID
- otherRoom.Exits[dir] = exit
- changed = true
- }
- if changed {
- otherPath, pathOk := s.world.GetRoomPath(otherID)
- if pathOk {
- writeYAMLFile(otherPath, otherRoom)
- exitUpdates++
- }
+ if !otherRoom.RewriteRoomIDs(idMap) {
+ continue
+ }
+ otherPath, pathOk := s.world.GetRoomPath(otherID)
+ if !pathOk {
+ continue
}
+ writeYAMLFile(otherPath, otherRoom)
+ refUpdates++
+ }
+
+ // Migrate room-ID-embedded state across all characters (discovered-exit
+ // player flags, RoomID, EnterSeqRoom, MapSymbols, RoomsVisited) so a
+ // rename does not strand players or leave stale hidden_exit_<id>_<dir>
+ // flags pointing at the old room ID.
+ if s.rewriteRoomIDs != nil {
+ s.rewriteRoomIDs(idMap)
}
s.undoStack.Push(ChangeDesc{
- Description: fmt.Sprintf("rename room %d to %d (updated %d exits)", body.ID, body.NewID, exitUpdates),
+ Description: fmt.Sprintf("rename room %d to %d (updated %d refs)", body.ID, body.NewID, refUpdates),
FilePath: oldPath,
NewFilePath: newPath,
OldContent: data,
@@ -941,6 +944,11 @@ func (s *AdminServer) handleResolveDuplicate(w http.ResponseWriter, r *http.Requ
writeJSON(w, map[string]any{"error": "yaml parse failed: " + err.Error()})
return
}
+ // A duplicate file was never in the room index (only one of the pair
+ // is indexed), so no player has visited it and no other room points at
+ // it. Renaming it to an unused ID therefore needs no exit/trigger/wander
+ // reference rewrite and no player-state migration — only its own id
+ // field and filename change.
m["id"] = body.NewID
newContent, err := writeMapAsYAML(newRel, m)