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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
from .generated import data_pb2 as data_pb2
import pkgutil
class Lingo2StaticLogic:
item_id_to_name: dict[int, str]
location_id_to_name: dict[int, str]
item_name_to_id: dict[str, int]
location_name_to_id: dict[str, int]
def __init__(self):
self.item_id_to_name = {}
self.location_id_to_name = {}
file = pkgutil.get_data(__name__, "generated/data.binpb")
self.objects = data_pb2.AllObjects()
self.objects.ParseFromString(bytearray(file))
for door in self.objects.doors:
if door.type in [data_pb2.DoorType.STANDARD, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
location_name = self.get_door_location_name(door)
self.location_id_to_name[door.ap_id] = location_name
if door.type not in [data_pb2.DoorType.EVENT, data_pb2.DoorType.LOCATION_ONLY, data_pb2.DoorType.GRAVESTONE]:
item_name = self.get_door_item_name(door)
self.item_id_to_name[door.ap_id] = item_name
for letter in self.objects.letters:
letter_name = f"{letter.key.upper()}{'2' if letter.level2 else '1'}"
location_name = f"{self.get_room_object_map_name(letter)} - {letter_name}"
self.location_id_to_name[letter.ap_id] = location_name
if not letter.level2:
self.item_id_to_name[letter.ap_id] = letter_name
for mastery in self.objects.masteries:
location_name = f"{self.get_room_object_map_name(mastery)} - Mastery"
self.location_id_to_name[mastery.ap_id] = location_name
for ending in self.objects.endings:
location_name = f"{self.get_room_object_map_name(ending)} - {ending.name.title()} Ending"
self.location_id_to_name[ending.ap_id] = location_name
for progressive in self.objects.progressives:
self.item_id_to_name[progressive.ap_id] = progressive.name
self.item_id_to_name[self.objects.special_ids["Nothing"]] = "Nothing"
self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()}
self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()}
def get_door_item_name(self, door: data_pb2.Door) -> str:
return f"{self.get_map_object_map_name(door)} - {door.name}"
def get_door_item_name_by_id(self, door_id: int) -> str:
door = self.objects.doors[door_id]
return self.get_door_item_name(door_id)
def get_door_location_name(self, door: data_pb2.Door) -> str:
game_map = self.objects.maps[door.map_id]
room = self.objects.rooms[door.room_id]
if room.HasField("panel_display_name"):
map_part = f"{game_map.display_name} ({room.panel_display_name})"
else:
map_part = game_map.display_name
if door.HasField("location_name"):
return f"{map_part} - {door.location_name}"
generated_location_name = self.get_generated_door_location_name(door)
if generated_location_name is not None:
return generated_location_name
return f"{map_part} - {door.name}"
def get_generated_door_location_name(self, door: data_pb2.Door) -> str | None:
if door.type != data_pb2.DoorType.STANDARD:
return None
if len(door.keyholders) > 0 or len(door.endings) > 0:
return None
if len(door.panels) > 4:
return None
map_areas = set()
for panel_id in door.panels:
panel = self.objects.panels[panel_id.panel]
panel_room = self.objects.rooms[panel.room_id]
# It's okay if panel_display_name is not present because then it's coalesced with other unnamed areas.
map_areas.add(panel_room.panel_display_name)
if len(map_areas) > 1:
return None
game_map = self.objects.maps[door.map_id]
map_area = map_areas.pop()
if map_area == "":
map_part = game_map.display_name
else:
map_part = f"{game_map.display_name} ({map_area})"
def get_panel_display_name(panel: data_pb2.ProxyIdentifier) -> str:
panel_data = self.objects.panels[panel.panel]
panel_name = panel_data.display_name if panel_data.HasField("display_name") else panel_data.name
if panel.HasField("answer"):
return f"{panel_name}/{panel.answer.upper()}"
else:
return panel_name
panel_names = [get_panel_display_name(panel_id)
for panel_id in door.panels]
panel_names.sort()
return f"{map_part} - {", ".join(panel_names)}"
def get_door_location_name_by_id(self, door_id: int) -> str:
door = self.objects.doors[door_id]
return self.get_door_location_name(door)
def get_room_region_name(self, room_id: int) -> str:
room = self.objects.rooms[room_id]
return f"{self.get_map_object_map_name(room)} - {room.name}"
def get_map_object_map_name(self, obj) -> str:
return self.objects.maps[obj.map_id].display_name
def get_room_object_map_name(self, obj) -> str:
return self.get_map_object_map_name(self.objects.rooms[obj.room_id])
|