From 7544b11c86fd597321a507747fbd0fe1491ccbd8 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Wed, 22 Oct 2025 21:58:43 -0400 Subject: Implemented latched doors in the client --- apworld/context.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'apworld/context.py') diff --git a/apworld/context.py b/apworld/context.py index d59bf9d..7975686 100644 --- a/apworld/context.py +++ b/apworld/context.py @@ -38,6 +38,7 @@ class Lingo2Manager: keyboard: dict[str, int] worldports: set[int] goaled: bool + latches: set[int] def __init__(self, game_ctx: "Lingo2GameContext", client_ctx: "Lingo2ClientContext"): self.game_ctx = game_ctx @@ -47,6 +48,7 @@ class Lingo2Manager: self.tracker = Tracker(self) self.keyboard = {} self.worldports = set() + self.latches = set() self.reset() @@ -56,6 +58,7 @@ class Lingo2Manager: self.worldports = set() self.goaled = False + self.latches = set() def update_keyboard(self, new_keyboard: dict[str, int]) -> dict[str, int]: ret: dict[str, int] = {} @@ -81,6 +84,12 @@ class Lingo2Manager: return ret + def update_latches(self, new_latches: set[int]) -> set[int]: + ret = new_latches.difference(self.latches) + self.latches.update(new_latches) + + return ret + class Lingo2GameContext: server: Endpoint | None @@ -244,6 +253,17 @@ class Lingo2GameContext: async_start(self.send_msgs([msg]), name="path reply") + def send_update_latches(self, latches): + if self.server is None: + return + + msg = { + "cmd": "UpdateLatches", + "latches": latches, + } + + async_start(self.send_msgs([msg]), name="update latches") + 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: @@ -298,7 +318,7 @@ class Lingo2ClientContext(CommonContext): self.victory_data_storage_key = f"_read_client_status_{self.team}_{self.slot}" self.set_notify(self.get_datastorage_key("keyboard1"), self.get_datastorage_key("keyboard2"), - self.victory_data_storage_key) + self.victory_data_storage_key, self.get_datastorage_key("latches")) msg_batch = [{ "cmd": "Set", "key": self.get_datastorage_key("keyboard1"), @@ -311,6 +331,12 @@ class Lingo2ClientContext(CommonContext): "default": 0, "want_reply": True, "operations": [{"operation": "default", "value": 0}] + }, { + "cmd": "Set", + "key": self.get_datastorage_key("latches"), + "default": [], + "want_reply": True, + "operations": [{"operation": "default", "value": []}] }] if self.slot_data.get("shuffle_worldports", False): @@ -420,6 +446,10 @@ class Lingo2ClientContext(CommonContext): self.manager.game_ctx.send_update_worldports(updates) elif args["key"] == self.victory_data_storage_key: self.handle_status_update(args["value"]) + elif args["key"] == self.get_datastorage_key("latches"): + updates = self.manager.update_latches(set(args["value"])) + if len(updates) > 0: + self.manager.game_ctx.send_update_latches(updates) def get_datastorage_key(self, name: str): return f"Lingo2_{self.slot}_{name}" @@ -501,6 +531,17 @@ class Lingo2ClientContext(CommonContext): self.manager.tracker.refresh_state() self.manager.game_ctx.send_accessible_locations() + async def update_latches(self, updates: set[int]): + await self.send_msgs([{ + "cmd": "Set", + "key": self.get_datastorage_key("latches"), + "want_reply": True, + "operations": [{ + "operation": "update", + "value": updates + }] + }]) + async def pipe_loop(manager: Lingo2Manager): while not manager.client_ctx.exit_event.is_set(): @@ -571,6 +612,10 @@ async def process_game_cmd(manager: Lingo2Manager, args: dict): path = manager.tracker.get_path_to_goal() manager.game_ctx.send_path_reply(args["type"], args.get("id", None), path) + elif cmd == "LatchDoor": + updates = manager.update_latches({args["door"]}) + if len(updates) > 0: + async_start(manager.client_ctx.update_latches(updates), name="client update latches") elif cmd == "Quit": manager.client_ctx.exit_event.set() -- cgit 1.4.1