about summary refs log tree commit diff stats
path: root/apworld/context.py
diff options
context:
space:
mode:
Diffstat (limited to 'apworld/context.py')
-rw-r--r--apworld/context.py72
1 files changed, 67 insertions, 5 deletions
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:
35 tracker: Tracker 35 tracker: Tracker
36 36
37 keyboard: dict[str, int] 37 keyboard: dict[str, int]
38 worldports: set[int]
38 39
39 def __init__(self, game_ctx: "Lingo2GameContext", client_ctx: "Lingo2ClientContext"): 40 def __init__(self, game_ctx: "Lingo2GameContext", client_ctx: "Lingo2ClientContext"):
40 self.game_ctx = game_ctx 41 self.game_ctx = game_ctx
@@ -43,6 +44,7 @@ class Lingo2Manager:
43 self.client_ctx.manager = self 44 self.client_ctx.manager = self
44 self.tracker = Tracker(self) 45 self.tracker = Tracker(self)
45 self.keyboard = {} 46 self.keyboard = {}
47 self.worldports = set()
46 48
47 self.reset() 49 self.reset()
48 50
@@ -50,6 +52,8 @@ class Lingo2Manager:
50 for k in ALL_LETTERS: 52 for k in ALL_LETTERS:
51 self.keyboard[k] = 0 53 self.keyboard[k] = 0
52 54
55 self.worldports = set()
56
53 def update_keyboard(self, new_keyboard: dict[str, int]) -> dict[str, int]: 57 def update_keyboard(self, new_keyboard: dict[str, int]) -> dict[str, int]:
54 ret: dict[str, int] = {} 58 ret: dict[str, int] = {}
55 59
@@ -64,6 +68,16 @@ class Lingo2Manager:
64 68
65 return ret 69 return ret
66 70
71 def update_worldports(self, new_worldports: set[int]) -> set[int]:
72 ret = new_worldports.difference(self.worldports)
73 self.worldports.update(new_worldports)
74
75 if len(ret) > 0:
76 self.tracker.refresh_state()
77 self.game_ctx.send_accessible_locations()
78
79 return ret
80
67 81
68class Lingo2GameContext: 82class Lingo2GameContext:
69 server: Endpoint | None 83 server: Endpoint | None
@@ -160,6 +174,9 @@ class Lingo2GameContext:
160 "locations": list(self.manager.tracker.accessible_locations), 174 "locations": list(self.manager.tracker.accessible_locations),
161 } 175 }
162 176
177 if len(self.manager.tracker.accessible_worldports) > 0:
178 msg["worldports"] = list(self.manager.tracker.accessible_worldports)
179
163 async_start(self.send_msgs([msg]), name="accessible locations") 180 async_start(self.send_msgs([msg]), name="accessible locations")
164 181
165 def send_update_locations(self, locations): 182 def send_update_locations(self, locations):
@@ -184,6 +201,17 @@ class Lingo2GameContext:
184 201
185 async_start(self.send_msgs([msg]), name="update keyboard") 202 async_start(self.send_msgs([msg]), name="update keyboard")
186 203
204 def send_update_worldports(self, worldports):
205 if self.server is None:
206 return
207
208 msg = {
209 "cmd": "UpdateWorldports",
210 "worldports": worldports,
211 }
212
213 async_start(self.send_msgs([msg]), name="update worldports")
214
187 async def send_msgs(self, msgs: list[Any]) -> None: 215 async def send_msgs(self, msgs: list[Any]) -> None:
188 """ `msgs` JSON serializable """ 216 """ `msgs` JSON serializable """
189 if not self.server or not self.server.socket.open or self.server.socket.closed: 217 if not self.server or not self.server.socket.open or self.server.socket.closed:
@@ -226,7 +254,7 @@ class Lingo2ClientContext(CommonContext):
226 self.manager.game_ctx.send_accessible_locations() 254 self.manager.game_ctx.send_accessible_locations()
227 255
228 self.set_notify(self.get_datastorage_key("keyboard1"), self.get_datastorage_key("keyboard2")) 256 self.set_notify(self.get_datastorage_key("keyboard1"), self.get_datastorage_key("keyboard2"))
229 async_start(self.send_msgs([{ 257 msg_batch = [{
230 "cmd": "Set", 258 "cmd": "Set",
231 "key": self.get_datastorage_key("keyboard1"), 259 "key": self.get_datastorage_key("keyboard1"),
232 "default": 0, 260 "default": 0,
@@ -238,7 +266,19 @@ class Lingo2ClientContext(CommonContext):
238 "default": 0, 266 "default": 0,
239 "want_reply": True, 267 "want_reply": True,
240 "operations": [{"operation": "default", "value": 0}] 268 "operations": [{"operation": "default", "value": 0}]
241 }]), name="default keys") 269 }]
270
271 if self.slot_data["shuffle_worldports"]:
272 self.set_notify(self.get_datastorage_key("worldports"))
273 msg_batch.append({
274 "cmd": "Set",
275 "key": self.get_datastorage_key("worldports"),
276 "default": [],
277 "want_reply": True,
278 "operations": [{"operation": "default", "value": []}]
279 })
280
281 async_start(self.send_msgs(msg_batch), name="default keys")
242 elif cmd == "RoomUpdate": 282 elif cmd == "RoomUpdate":
243 self.manager.tracker.set_checked_locations(self.checked_locations) 283 self.manager.tracker.set_checked_locations(self.checked_locations)
244 self.manager.game_ctx.send_update_locations(args["checked_locations"]) 284 self.manager.game_ctx.send_update_locations(args["checked_locations"])
@@ -276,7 +316,7 @@ class Lingo2ClientContext(CommonContext):
276 316
277 if args["type"] == "Hint" and not args.get("found", False): 317 if args["type"] == "Hint" and not args.get("found", False):
278 self.manager.game_ctx.send_hint_received(item_name, location_name, receiver_name, args["item"].flags, 318 self.manager.game_ctx.send_hint_received(item_name, location_name, receiver_name, args["item"].flags,
279 int(args["receiving"]) == self.slot) 319 int(args["receiving"]) == self.slot)
280 elif args["receiving"] != self.slot: 320 elif args["receiving"] != self.slot:
281 self.manager.game_ctx.send_item_sent_notification(item_name, receiver_name, args["item"].flags) 321 self.manager.game_ctx.send_item_sent_notification(item_name, receiver_name, args["item"].flags)
282 322
@@ -324,6 +364,10 @@ class Lingo2ClientContext(CommonContext):
324 self.handle_keyboard_update(1, args) 364 self.handle_keyboard_update(1, args)
325 elif args["key"] == self.get_datastorage_key("keyboard2"): 365 elif args["key"] == self.get_datastorage_key("keyboard2"):
326 self.handle_keyboard_update(2, args) 366 self.handle_keyboard_update(2, args)
367 elif args["key"] == self.get_datastorage_key("worldports"):
368 updates = self.manager.update_worldports(set(args["value"]))
369 if len(updates) > 0:
370 self.manager.game_ctx.send_update_worldports(updates)
327 371
328 def get_datastorage_key(self, name: str): 372 def get_datastorage_key(self, name: str):
329 return f"Lingo2_{self.slot}_{name}" 373 return f"Lingo2_{self.slot}_{name}"
@@ -373,8 +417,6 @@ class Lingo2ClientContext(CommonContext):
373 }) 417 })
374 418
375 if len(msgs) > 0: 419 if len(msgs) > 0:
376 print(updates)
377 print(msgs)
378 await self.send_msgs(msgs) 420 await self.send_msgs(msgs)
379 421
380 def handle_keyboard_update(self, field: int, args: dict[str, Any]): 422 def handle_keyboard_update(self, field: int, args: dict[str, Any]):
@@ -391,6 +433,17 @@ class Lingo2ClientContext(CommonContext):
391 if len(updates) > 0: 433 if len(updates) > 0:
392 self.manager.game_ctx.send_update_keyboard(updates) 434 self.manager.game_ctx.send_update_keyboard(updates)
393 435
436 async def update_worldports(self, updates: set[int]):
437 await self.send_msgs([{
438 "cmd": "Set",
439 "key": self.get_datastorage_key("worldports"),
440 "want_reply": True,
441 "operations": [{
442 "operation": "update",
443 "value": updates
444 }]
445 }])
446
394 447
395async def pipe_loop(manager: Lingo2Manager): 448async def pipe_loop(manager: Lingo2Manager):
396 while not manager.client_ctx.exit_event.is_set(): 449 while not manager.client_ctx.exit_event.is_set():
@@ -433,6 +486,15 @@ async def process_game_cmd(manager: Lingo2Manager, args: dict):
433 updates = manager.update_keyboard(args["keyboard"]) 486 updates = manager.update_keyboard(args["keyboard"])
434 if len(updates) > 0: 487 if len(updates) > 0:
435 async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard") 488 async_start(manager.client_ctx.update_keyboard(updates), name="client update keyboard")
489 elif cmd == "CheckWorldport":
490 port_id = args["port_id"]
491 worldports = {port_id}
492 if str(port_id) in manager.client_ctx.slot_data["port_pairings"]:
493 worldports.add(manager.client_ctx.slot_data["port_pairings"][str(port_id)])
494
495 updates = manager.update_worldports(worldports)
496 if len(updates) > 0:
497 async_start(manager.client_ctx.update_worldports(updates), name="client update worldports")
436 elif cmd == "Quit": 498 elif cmd == "Quit":
437 manager.client_ctx.exit_event.set() 499 manager.client_ctx.exit_event.set()
438 500