aboutsummaryrefslogtreecommitdiff
path: root/internal/world/rekey_objects_test.go
blob: 908e30b9dc6fdf2dafe7ba8d2a16d9d9cd217666 (plain)
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
package world

import "testing"

// TestRekeyRoomsUpdatesObjStateRoomID: object lookups filter on ObjState.RoomID
// while GetObjState looks up the map key, so the invariant
// mapKey == ObjStateKey(st.RoomID, ...) must survive a rekey. Leaving RoomID
// stale makes room objects vanish from a renamed/swapped room for the rest of
// the process and lets TickObjWander create a duplicate entry for the state.
func TestRekeyRoomsUpdatesObjStateRoomID(t *testing.T) {
	w := New(t.TempDir())
	w.objStates[w.ObjStateKey(1, "anvil", 0)] = &ObjState{
		RoomID:      1,
		DefID:       "anvil",
		Index:       0,
		WanderRooms: []int{1, 5, 9},
	}

	w.RekeyRooms(map[int]int{1: 3, 5: 7})

	inst := w.GetObjState(3, "anvil", 0)
	if inst == nil {
		t.Fatal("object state lost after rekey")
	}
	if inst.RoomID != 3 {
		t.Fatalf("ObjState.RoomID = %d, want 3 (map key and state desynchronised)", inst.RoomID)
	}
	if got := inst.WanderRooms; len(got) != 3 || got[0] != 3 || got[1] != 7 || got[2] != 9 {
		t.Fatalf("WanderRooms after rekey = %v, want [3 7 9]", got)
	}
	if got := w.AllObjInstances(3); len(got) != 1 {
		t.Fatalf("AllObjInstances(3) = %d entries, want 1 (object invisible in renamed room)", len(got))
	}
	if got := w.AllObjInstances(1); len(got) != 0 {
		t.Fatalf("AllObjInstances(1) = %d entries, want 0 (stale old room)", len(got))
	}
}

// Regression: an object away from its home room is keyed by its current room,
// so the old key-driven walk left its HomeRoomID/WanderRooms stale and a later
// entry to the renamed home created a duplicate instance.
func TestRekeyRoomsUpdatesAwayFromHomeObject(t *testing.T) {
	w := New(t.TempDir())
	// Declared in home room 1, currently wandering in room 5.
	w.objStates[w.ObjStateKey(5, "fishing_spot", 0)] = &ObjState{
		RoomID:      5,
		HomeRoomID:  1,
		DefID:       "fishing_spot",
		Index:       0,
		WanderRooms: []int{1, 5},
	}

	w.RekeyRooms(map[int]int{1: 20})

	inst := w.GetObjState(5, "fishing_spot", 0)
	if inst == nil {
		t.Fatal("away object state lost after rekey")
	}
	if inst.HomeRoomID != 20 {
		t.Fatalf("HomeRoomID = %d, want 20", inst.HomeRoomID)
	}
	if got := inst.WanderRooms; len(got) != 2 || got[0] != 20 || got[1] != 5 {
		t.Fatalf("WanderRooms = %v, want [20 5]", got)
	}
}