about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--apworld/client/gamedata.gd2
-rw-r--r--apworld/client/manager.gd5
-rw-r--r--apworld/client/textclient.gd94
-rw-r--r--apworld/context.py6
-rw-r--r--data/maps/the_great/doors.txtpb2
-rw-r--r--data/maps/the_parthenon/rooms/Main Area.txtpb4
7 files changed, 115 insertions, 7 deletions
diff --git a/README.md b/README.md index 8b1a425..9af22a3 100644 --- a/README.md +++ b/README.md
@@ -132,6 +132,15 @@ before leaving solve mode, as the keyholder will still be considered to be
132"focused", even though it has moved. If you have already moved, though, there is 132"focused", even though it has moved. If you have already moved, though, there is
133another way to get your letters back: just use the Key Return in The Entry. 133another way to get your letters back: just use the Key Return in The Entry.
134 134
135### Why is the tracker telling me to solve a panel that's currently red?
136
137Red usually indicates that a panel cannot be solved because of missing letters.
138However, that only applies to the puzzle's main answer. If a puzzle has
139alternate answers, you may be expected to use one of those instead of the main
140one. As long as you have all of the necessary letters, an alternate answer can
141be typed into a red panel even though it does not show you typing. When you
142finish typing the answer, the panel will solve as normal.
143
135## Running from source 144## Running from source
136 145
137The randomizer is mostly written in Python and GDScript, which do not need to be 146The randomizer is mostly written in Python and GDScript, which do not need to be
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index 8e909dd..1424721 100644 --- a/apworld/client/gamedata.gd +++ b/apworld/client/gamedata.gd
@@ -175,7 +175,7 @@ func get_door_receivers(door_id):
175 175
176func get_worldport_display_name(port_id): 176func get_worldport_display_name(port_id):
177 var port = objects.get_ports()[port_id] 177 var port = objects.get_ports()[port_id]
178 return "%s - %s" % [_get_room_object_map_name(port), port.get_name()] 178 return "%s - %s" % [_get_room_object_map_name(port), port.get_display_name()]
179 179
180 180
181func _get_map_object_map_name(obj): 181func _get_map_object_map_name(obj):
diff --git a/apworld/client/manager.gd b/apworld/client/manager.gd index 3facfba..5b731d2 100644 --- a/apworld/client/manager.gd +++ b/apworld/client/manager.gd
@@ -333,6 +333,7 @@ func _on_checked_worldports_updated():
333 var textclient_node = global.get_node("Textclient") 333 var textclient_node = global.get_node("Textclient")
334 if textclient_node != null: 334 if textclient_node != null:
335 textclient_node.update_locations() 335 textclient_node.update_locations()
336 textclient_node.update_worldports()
336 337
337 338
338func _client_could_not_connect(message): 339func _client_could_not_connect(message):
@@ -449,6 +450,10 @@ func _client_connected(slot_data):
449 450
450 _inverse_item_locks[lock[0]].append([door_id, lock[1]]) 451 _inverse_item_locks[lock[0]].append([door_id, lock[1]])
451 452
453 if shuffle_worldports:
454 var textclient = global.get_node("Textclient")
455 textclient.setup_worldports()
456
452 ap_connected.emit() 457 ap_connected.emit()
453 458
454 459
diff --git a/apworld/client/textclient.gd b/apworld/client/textclient.gd index 1a0ce5c..0c4e675 100644 --- a/apworld/client/textclient.gd +++ b/apworld/client/textclient.gd
@@ -8,10 +8,14 @@ var tracker_label
8var is_open = false 8var is_open = false
9 9
10var locations_overlay 10var locations_overlay
11
12var location_texture 11var location_texture
13var worldport_texture 12var worldport_texture
14 13
14var worldports_tab
15var worldports_tree
16var port_tree_item_by_map = {}
17var port_tree_item_by_map_port = {}
18
15 19
16func _ready(): 20func _ready():
17 process_mode = ProcessMode.PROCESS_MODE_ALWAYS 21 process_mode = ProcessMode.PROCESS_MODE_ALWAYS
@@ -87,6 +91,22 @@ func _ready():
87 tracker_label = RichTextLabel.new() 91 tracker_label = RichTextLabel.new()
88 tracker_margins.add_child(tracker_label) 92 tracker_margins.add_child(tracker_label)
89 93
94 worldports_tab = MarginContainer.new()
95 worldports_tab.name = "Worldports"
96 worldports_tab.add_theme_constant_override("margin_top", 60)
97 worldports_tab.add_theme_constant_override("margin_left", 60)
98 worldports_tab.add_theme_constant_override("margin_right", 60)
99 worldports_tab.add_theme_constant_override("margin_bottom", 60)
100 tabs.add_child(worldports_tab)
101 tabs.set_tab_hidden(2, true)
102
103 worldports_tree = Tree.new()
104 worldports_tree.columns = 2
105 worldports_tree.hide_root = true
106 worldports_tree.theme = preload("res://assets/themes/baseUI.tres")
107 worldports_tree.add_theme_font_size_override("font_size", 24)
108 worldports_tab.add_child(worldports_tree)
109
90 var runtime = global.get_node("Runtime") 110 var runtime = global.get_node("Runtime")
91 var location_image = Image.new() 111 var location_image = Image.new()
92 location_image.load_png_from_buffer(runtime.read_path("assets/location.png")) 112 location_image.load_png_from_buffer(runtime.read_path("assets/location.png"))
@@ -199,5 +219,77 @@ func update_locations_visibility():
199 locations_overlay.visible = ap.show_locations 219 locations_overlay.visible = ap.show_locations
200 220
201 221
222func setup_worldports():
223 tabs.set_tab_hidden(2, false)
224
225 var root_ti = worldports_tree.create_item(null)
226
227 var ports_by_map_id = {}
228 var display_names_by_map_id = {}
229 var display_names_by_port_id = {}
230
231 var ap = global.get_node("Archipelago")
232 var gamedata = global.get_node("Gamedata")
233 for fpid in ap.port_pairings:
234 var port = gamedata.objects.get_ports()[fpid]
235 var room = gamedata.objects.get_rooms()[port.get_room_id()]
236
237 if not ports_by_map_id.has(room.get_map_id()):
238 ports_by_map_id[room.get_map_id()] = []
239
240 var map = gamedata.objects.get_maps()[room.get_map_id()]
241 display_names_by_map_id[map.get_id()] = map.get_display_name()
242
243 ports_by_map_id[room.get_map_id()].append(fpid)
244 display_names_by_port_id[fpid] = port.get_display_name()
245
246 var sorted_map_ids = ports_by_map_id.keys().duplicate()
247 sorted_map_ids.sort_custom(
248 func(a, b): return display_names_by_map_id[a] < display_names_by_map_id[b]
249 )
250
251 for map_id in sorted_map_ids:
252 var map_ti = root_ti.create_child()
253 map_ti.set_text(0, display_names_by_map_id[map_id])
254 map_ti.visible = false
255 map_ti.collapsed = true
256 port_tree_item_by_map[map_id] = map_ti
257 port_tree_item_by_map_port[map_id] = {}
258
259 var port_ids = ports_by_map_id[map_id]
260 port_ids.sort_custom(
261 func(a, b): return display_names_by_port_id[a] < display_names_by_port_id[b]
262 )
263
264 for port_id in port_ids:
265 var port_ti = map_ti.create_child()
266 port_ti.set_text(0, display_names_by_port_id[port_id])
267 port_ti.set_text(1, gamedata.get_worldport_display_name(ap.port_pairings[port_id]))
268 port_ti.visible = false
269 port_tree_item_by_map_port[map_id][port_id] = port_ti
270
271 update_worldports()
272
273
274func update_worldports():
275 var ap = global.get_node("Archipelago")
276
277 for map_id in port_tree_item_by_map_port.keys():
278 var map_visible = false
279
280 for port_id in port_tree_item_by_map_port[map_id].keys():
281 var ti = port_tree_item_by_map_port[map_id][port_id]
282 ti.visible = ap.client._checked_worldports.has(port_id)
283
284 if ti.visible:
285 map_visible = true
286
287 port_tree_item_by_map[map_id].visible = map_visible
288
289
202func reset(): 290func reset():
203 locations_overlay.clear() 291 locations_overlay.clear()
292 tabs.set_tab_hidden(2, true)
293 port_tree_item_by_map.clear()
294 port_tree_item_by_map_port.clear()
295 worldports_tree.clear()
diff --git a/apworld/context.py b/apworld/context.py index 4a85868..4b78517 100644 --- a/apworld/context.py +++ b/apworld/context.py
@@ -280,8 +280,9 @@ class Lingo2ClientContext(CommonContext):
280 280
281 async_start(self.send_msgs(msg_batch), name="default keys") 281 async_start(self.send_msgs(msg_batch), name="default keys")
282 elif cmd == "RoomUpdate": 282 elif cmd == "RoomUpdate":
283 self.manager.tracker.set_checked_locations(self.checked_locations) 283 if "checked_locations" in args:
284 self.manager.game_ctx.send_update_locations(args["checked_locations"]) 284 self.manager.tracker.set_checked_locations(self.checked_locations)
285 self.manager.game_ctx.send_update_locations(args["checked_locations"])
285 elif cmd == "ReceivedItems": 286 elif cmd == "ReceivedItems":
286 self.manager.tracker.set_collected_items(self.items_received) 287 self.manager.tracker.set_collected_items(self.items_received)
287 288
@@ -495,6 +496,7 @@ async def process_game_cmd(manager: Lingo2Manager, args: dict):
495 updates = manager.update_worldports(worldports) 496 updates = manager.update_worldports(worldports)
496 if len(updates) > 0: 497 if len(updates) > 0:
497 async_start(manager.client_ctx.update_worldports(updates), name="client update worldports") 498 async_start(manager.client_ctx.update_worldports(updates), name="client update worldports")
499 manager.game_ctx.send_update_worldports(updates)
498 elif cmd == "Quit": 500 elif cmd == "Quit":
499 manager.client_ctx.exit_event.set() 501 manager.client_ctx.exit_event.set()
500 502
diff --git a/data/maps/the_great/doors.txtpb b/data/maps/the_great/doors.txtpb index abbbc11..628715f 100644 --- a/data/maps/the_great/doors.txtpb +++ b/data/maps/the_great/doors.txtpb
@@ -60,7 +60,7 @@ doors {
60doors { 60doors {
61 name: "Control Center Gray Door" 61 name: "Control Center Gray Door"
62 type: CONTROL_CENTER_COLOR 62 type: CONTROL_CENTER_COLOR
63 receivers: "Components/Doors/Gates/Gate" 63 receivers: "Components/Doors/Gates/Gate/animationListener"
64 control_center_color: "gray" 64 control_center_color: "gray"
65} 65}
66doors { 66doors {
diff --git a/data/maps/the_parthenon/rooms/Main Area.txtpb b/data/maps/the_parthenon/rooms/Main Area.txtpb index 79f5e8f..2d989f8 100644 --- a/data/maps/the_parthenon/rooms/Main Area.txtpb +++ b/data/maps/the_parthenon/rooms/Main Area.txtpb
@@ -55,14 +55,14 @@ panels {
55} 55}
56ports { 56ports {
57 name: "GALLERY" 57 name: "GALLERY"
58 display_name: "Building Worldport" 58 display_name: "Columns Worldport"
59 path: "Components/Warps/worldport" 59 path: "Components/Warps/worldport"
60 destination { x: 0 y: 0 z: 0 } 60 destination { x: 0 y: 0 z: 0 }
61 rotation: 0 61 rotation: 0
62} 62}
63ports { 63ports {
64 name: "ENTRY" 64 name: "ENTRY"
65 display_name: "Columns Worldport" 65 display_name: "Building Worldport"
66 path: "Components/Warps/worldport2" 66 path: "Components/Warps/worldport2"
67 destination { x: 0 y: 0 z: -21 } 67 destination { x: 0 y: 0 z: -21 }
68 rotation: 0 68 rotation: 0