From 53e0509fcb20cc824e3fe5b3d3a826f09fc9c166 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 27 Sep 2025 21:06:32 -0400 Subject: Treat worldports as items for tracker --- apworld/context.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) (limited to 'apworld/context.py') diff --git a/apworld/context.py b/apworld/context.py index bc3b1bf..4a85868 100644 --- a/apworld/context.py +++ b/apworld/context.py @@ -35,6 +35,7 @@ class Lingo2Manager: tracker: Tracker keyboard: dict[str, int] + worldports: set[int] def __init__(self, game_ctx: "Lingo2GameContext", client_ctx: "Lingo2ClientContext"): self.game_ctx = game_ctx @@ -43,6 +44,7 @@ class Lingo2Manager: self.client_ctx.manager = self self.tracker = Tracker(self) self.keyboard = {} + self.worldports = set() self.reset() @@ -50,6 +52,8 @@ class Lingo2Manager: for k in ALL_LETTERS: self.keyboard[k] = 0 + self.worldports = set() + def update_keyboard(self, new_keyboard: dict[str, int]) -> dict[str, int]: ret: dict[str, int] = {} @@ -64,6 +68,16 @@ class Lingo2Manager: return ret + def update_worldports(self, new_worldports: set[int]) -> set[int]: + ret = new_worldports.difference(self.worldports) + self.worldports.update(new_worldports) + + if len(ret) > 0: + self.tracker.refresh_state() + self.game_ctx.send_accessible_locations() + + return ret + class Lingo2GameContext: server: Endpoint | None @@ -160,6 +174,9 @@ class Lingo2GameContext: "locations": list(self.manager.tracker.accessible_locations), } + if len(self.manager.tracker.accessible_worldports) > 0: + msg["worldports"] = list(self.manager.tracker.accessible_worldports) + async_start(self.send_msgs([msg]), name="accessible locations") def send_update_locations(self, locations): @@ -184,6 +201,17 @@ class Lingo2GameContext: async_start(self.send_msgs([msg]), name="update keyboard") + def send_update_worldports(self, worldports): + if self.server is None: + return + + msg = { + "cmd": "UpdateWorldports", + "worldports": worldports, + } + + async_start(self.send_msgs([msg]), name="update worldports") + async def send_msgs(self, msgs: list[Any]) -> None: """ `msgs` JSON serializable """ if not self.server or not self.server.socket.open or self.server.socket.closed: @@ -226,7 +254,7 @@ class Lingo2ClientContext(CommonContext): self.manager.game_ctx.send_accessible_locations() self.set_notify(self.get_datastorage_key("keyboard1"), self.get_datastorage_key("keyboard2")) - async_start(self.send_msgs([{ + msg_batch = [{ "cmd": "Set", "key": self.get_datastorage_key("keyboard1"), "default": 0, @@ -238,7 +266,19 @@ class Lingo2ClientContext(CommonContext): "default": 0, "want_reply": True, "operations": [{"operation": "default", "value": 0}] - }]), name="default keys") + }] + + if self.slot_data["shuffle_worldports"]: + self.set_notify(self.get_datastorage_key("worldports")) + msg_batch.append({ + "cmd": "Set", + "key": self.get_datastorage_key("worldports"), + "default": [], + "want_reply": True, + "operations": [{"operation": "default", "value": []}] + }) + + async_start(self.send_msgs(msg_batch), name="default keys") elif cmd == "RoomUpdate": self.manager.tracker.set_checked_locations(self.checked_locations) self.manager.game_ctx.send_update_locations(args["checked_locations"]) @@ -276,7 +316,7 @@ class Lingo2ClientContext(CommonContext): if args["type"] == "Hint" and not args.get("found", False): self.manager.game_ctx.send_hint_received(item_name, location_name, receiver_name, args["item"].flags, - int(args["receiving"]) == self.slot) + int(args["receiving"]) == self.slot) elif args["receiving"] != self.slot: self.manager.game_ctx.send_item_sent_notification(item_name, receiver_name, args["item"].flags) @@ -324,6 +364,10 @@ class Lingo2ClientContext(CommonContext): self.handle_keyboard_update(1, args) elif args["key"] == self.get_datastorage_key("keyboard2"): self.handle_keyboard_update(2, args) + elif args["key"] == self.get_datastorage_key("worldports"): + updates = self.manager.update_worldports(set(args["value"])) + if len(updates) > 0: + self.manager.game_ctx.send_update_worldports(updates) def get_datastorage_key(self, name: str): return f"Lingo2_{self.slot}_{name}" @@ -373,8 +417,6 @@ class Lingo2ClientContext(CommonContext): }) if len(msgs) > 0: - print(updates) - print(msgs) await self.send_msgs(msgs) def handle_keyboard_update(self, field: int, args: dict[str, Any]): @@ -391,6 +433,17 @@ class Lingo2ClientContext(CommonContext): if len(updates) > 0: self.manager.game_ctx.send_update_keyboard(updates) + async def update_worldports(self, updates: set[int]): + await self.send_msgs([{ + "cmd": "Set", + "key": self.get_datastorage_key("worldports"), + "want_reply": True, + "operations": [{ + "operation": "update", + "value": updates + }] + }]) + async def pipe_loop(manager: Lingo2Manager): while not manager.client_ctx.exit_event.is_set(): @@ -433,6 +486,15 @@ async def process_game_cmd(manager: Lingo2Manager, args: dict): updates = manager.update_keyboard(args["keyboard"]) if len(updates) > 0: async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard") + elif cmd == "CheckWorldport": + port_id = args["port_id"] + worldports = {port_id} + if str(port_id) in manager.client_ctx.slot_data["port_pairings"]: + worldports.add(manager.client_ctx.slot_data["port_pairings"][str(port_id)]) + + updates = manager.update_worldports(worldports) + if len(updates) > 0: + async_start(manager.client_ctx.update_worldports(updates), name="client update worldports") elif cmd == "Quit": manager.client_ctx.exit_event.set() -- cgit 1.4.1