about summary refs log tree commit diff stats
path: root/apworld
diff options
context:
space:
mode:
Diffstat (limited to 'apworld')
-rw-r--r--apworld/__init__.py5
-rw-r--r--apworld/client/assets/location.pngbin0 -> 311 bytes
-rw-r--r--apworld/client/assets/worldport.pngbin0 -> 219 bytes
-rw-r--r--apworld/client/gamedata.gd2
-rw-r--r--apworld/client/manager.gd5
-rw-r--r--apworld/client/textclient.gd122
-rw-r--r--apworld/context.py6
-rw-r--r--apworld/logo.pngbin0 -> 9429 bytes
8 files changed, 133 insertions, 7 deletions
diff --git a/apworld/__init__.py b/apworld/__init__.py index 8da6d1f..1af31c0 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -12,7 +12,7 @@ from .player_logic import Lingo2PlayerLogic
12from .regions import create_regions, shuffle_entrances, connect_ports_from_ut 12from .regions import create_regions, shuffle_entrances, connect_ports_from_ut
13from .static_logic import Lingo2StaticLogic 13from .static_logic import Lingo2StaticLogic
14from .version import APWORLD_VERSION 14from .version import APWORLD_VERSION
15from ..LauncherComponents import Component, Type, components, launch as launch_component 15from ..LauncherComponents import Component, Type, components, launch as launch_component, icon_paths
16 16
17 17
18class Lingo2WebWorld(WebWorld): 18class Lingo2WebWorld(WebWorld):
@@ -163,6 +163,7 @@ def launch_client(*args):
163 launch_component(client_main, name="Lingo2Client", args=args) 163 launch_component(client_main, name="Lingo2Client", args=args)
164 164
165 165
166icon_paths["lingo2_ico"] = f"ap:{__name__}/logo.png"
166component = Component("Lingo 2 Client", component_type=Type.CLIENT, func=launch_client, 167component = Component("Lingo 2 Client", component_type=Type.CLIENT, func=launch_client,
167 description="Open Lingo 2.", supports_uri=True, game_name="Lingo 2") 168 description="Open Lingo 2.", supports_uri=True, game_name="Lingo 2", icon="lingo2_ico")
168components.append(component) 169components.append(component)
diff --git a/apworld/client/assets/location.png b/apworld/client/assets/location.png new file mode 100644 index 0000000..5304deb --- /dev/null +++ b/apworld/client/assets/location.png
Binary files differ
diff --git a/apworld/client/assets/worldport.png b/apworld/client/assets/worldport.png new file mode 100644 index 0000000..19dfdc3 --- /dev/null +++ b/apworld/client/assets/worldport.png
Binary files differ
diff --git a/apworld/client/gamedata.gd b/apworld/client/gamedata.gd index e44fa17..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 (Worldport)" % [_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 af155fb..0c4e675 100644 --- a/apworld/client/textclient.gd +++ b/apworld/client/textclient.gd
@@ -8,6 +8,13 @@ var tracker_label
8var is_open = false 8var is_open = false
9 9
10var locations_overlay 10var locations_overlay
11var location_texture
12var worldport_texture
13
14var worldports_tab
15var worldports_tree
16var port_tree_item_by_map = {}
17var port_tree_item_by_map_port = {}
11 18
12 19
13func _ready(): 20func _ready():
@@ -20,9 +27,10 @@ func _ready():
20 locations_overlay.offset_bottom = 720 27 locations_overlay.offset_bottom = 720
21 locations_overlay.offset_left = 20 28 locations_overlay.offset_left = 20
22 locations_overlay.anchor_right = 1.0 29 locations_overlay.anchor_right = 1.0
23 locations_overlay.offset_right = -20 30 locations_overlay.offset_right = -10
24 locations_overlay.scroll_active = false 31 locations_overlay.scroll_active = false
25 locations_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE 32 locations_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
33 locations_overlay.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST
26 add_child(locations_overlay) 34 add_child(locations_overlay)
27 update_locations_visibility() 35 update_locations_visibility()
28 36
@@ -83,6 +91,31 @@ func _ready():
83 tracker_label = RichTextLabel.new() 91 tracker_label = RichTextLabel.new()
84 tracker_margins.add_child(tracker_label) 92 tracker_margins.add_child(tracker_label)
85 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
110 var runtime = global.get_node("Runtime")
111 var location_image = Image.new()
112 location_image.load_png_from_buffer(runtime.read_path("assets/location.png"))
113 location_texture = ImageTexture.create_from_image(location_image)
114
115 var worldport_image = Image.new()
116 worldport_image.load_png_from_buffer(runtime.read_path("assets/worldport.png"))
117 worldport_texture = ImageTexture.create_from_image(worldport_image)
118
86 119
87func _input(event): 120func _input(event):
88 if global.loaded and event is InputEventKey and event.pressed: 121 if global.loaded and event is InputEventKey and event.pressed:
@@ -144,16 +177,22 @@ func update_locations():
144 locations_overlay.push_outline_color(Color(0, 0, 0, 1)) 177 locations_overlay.push_outline_color(Color(0, 0, 0, 1))
145 locations_overlay.push_outline_size(2) 178 locations_overlay.push_outline_size(2)
146 179
180 const kLocation = 0
181 const kWorldport = 1
182
147 var location_names = [] 183 var location_names = []
184 var type_by_name = {}
148 for location_id in ap.client._accessible_locations: 185 for location_id in ap.client._accessible_locations:
149 if not ap.client._checked_locations.has(location_id): 186 if not ap.client._checked_locations.has(location_id):
150 var location_name = gamedata.location_name_by_id.get(location_id, "(Unknown)") 187 var location_name = gamedata.location_name_by_id.get(location_id, "(Unknown)")
151 location_names.append(location_name) 188 location_names.append(location_name)
189 type_by_name[location_name] = kLocation
152 190
153 for port_id in ap.client._accessible_worldports: 191 for port_id in ap.client._accessible_worldports:
154 if not ap.client._checked_worldports.has(port_id): 192 if not ap.client._checked_worldports.has(port_id):
155 var port_name = gamedata.get_worldport_display_name(port_id) 193 var port_name = gamedata.get_worldport_display_name(port_id)
156 location_names.append(port_name) 194 location_names.append(port_name)
195 type_by_name[port_name] = kWorldport
157 196
158 location_names.sort() 197 location_names.sort()
159 198
@@ -161,7 +200,14 @@ func update_locations():
161 for location_name in location_names: 200 for location_name in location_names:
162 tracker_label.append_text("[p]%s[/p]" % location_name) 201 tracker_label.append_text("[p]%s[/p]" % location_name)
163 if count < 18: 202 if count < 18:
164 locations_overlay.append_text("[p align=right]%s[/p]" % location_name) 203 locations_overlay.push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT)
204 locations_overlay.append_text(location_name)
205 locations_overlay.append_text(" ")
206 if type_by_name[location_name] == kLocation:
207 locations_overlay.add_image(location_texture)
208 elif type_by_name[location_name] == kWorldport:
209 locations_overlay.add_image(worldport_texture)
210 locations_overlay.pop()
165 count += 1 211 count += 1
166 212
167 if count > 18: 213 if count > 18:
@@ -173,5 +219,77 @@ func update_locations_visibility():
173 locations_overlay.visible = ap.show_locations 219 locations_overlay.visible = ap.show_locations
174 220
175 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
176func reset(): 290func reset():
177 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/apworld/logo.png b/apworld/logo.png new file mode 100644 index 0000000..b9d00ba --- /dev/null +++ b/apworld/logo.png
Binary files differ