1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
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 {
var exitChanged bool
if remapInt(idMap, &exit.Room) {
exitChanged = true
}
for i := range exit.OnTraverse {
if exit.OnTraverse[i].Action != nil {
if remapInt(idMap, &exit.OnTraverse[i].Action.Teleport) {
exitChanged = true
}
if exit.OnTraverse[i].Action.SpawnMob != nil &&
remapIntSlice(idMap, exit.OnTraverse[i].Action.SpawnMob.DespawnRooms) {
exitChanged = true
}
}
}
if exitChanged {
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
}
|