From a51f7a53aa2c487ebf94ba0363038574ae8bb590 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 7 Jul 2026 00:22:32 -0400 Subject: feat: hidden exits (and related flags) work with commands that change room ids. exit code simplified and unified between impassable and blocked exits. --- internal/world/room_migrate.go | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 internal/world/room_migrate.go (limited to 'internal/world/room_migrate.go') diff --git a/internal/world/room_migrate.go b/internal/world/room_migrate.go new file mode 100644 index 0000000..6d79499 --- /dev/null +++ b/internal/world/room_migrate.go @@ -0,0 +1,71 @@ +package world + +// RewriteRoomIDs remaps every genuine room-ID reference in this room per idMap +// (oldID -> newID): exit targets, trigger Room/Teleport/DespawnRooms, on-enter +// Teleport/DespawnRooms, and mob WanderRooms. It does NOT touch author-chosen +// set_flags/set_player_flags values or condition `value:` fields — those are not +// structural room references (and historically the swapid regex rewrote them +// incorrectly as a side effect of matching any bare integer). +// +// idMap is assumed to be a bijection (each old ID maps to a distinct new ID); +// this holds for both swap (A<->B) and rename-to-unused (A->B). Returns whether +// any field was changed. +func (r *Room) RewriteRoomIDs(idMap map[int]int) bool { + if r == nil || len(idMap) == 0 { + return false + } + changed := false + for dir, exit := range r.Exits { + if remapInt(idMap, &exit.Room) { + r.Exits[dir] = exit + changed = true + } + } + for i := range r.Triggers { + if remapInt(idMap, &r.Triggers[i].Room) { + changed = true + } + for j := range r.Triggers[i].Steps { + s := &r.Triggers[i].Steps[j] + if remapInt(idMap, &s.Teleport) { + changed = true + } + if s.SpawnMob != nil && remapIntSlice(idMap, s.SpawnMob.DespawnRooms) { + changed = true + } + } + } + for i := range r.OnEnter { + s := &r.OnEnter[i] + if remapInt(idMap, &s.Teleport) { + changed = true + } + if s.SpawnMob != nil && remapIntSlice(idMap, s.SpawnMob.DespawnRooms) { + changed = true + } + } + for i := range r.Mobs { + if remapIntSlice(idMap, r.Mobs[i].WanderRooms) { + changed = true + } + } + return changed +} + +func remapInt(idMap map[int]int, n *int) bool { + if newID, ok := idMap[*n]; ok && newID != *n { + *n = newID + return true + } + return false +} + +func remapIntSlice(idMap map[int]int, slice []int) bool { + changed := false + for i := range slice { + if remapInt(idMap, &slice[i]) { + changed = true + } + } + return changed +} -- cgit v1.2.3