diff --git a/ZillionClient.py b/ZillionClient.py index d518f5ef..1ace8774 100644 --- a/ZillionClient.py +++ b/ZillionClient.py @@ -258,6 +258,10 @@ class ZillionContext(CommonContext): assert id_ in id_to_loc self.loc_mem_to_id[mem] = id_ + if len(self.loc_mem_to_id) != 394: + logger.warn("invalid Zillion `Connected` packet, " + f"`slot_data` missing locations in `loc_mem_to_id` - len {len(self.loc_mem_to_id)}") + self.got_slot_data.set() payload = { diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index b8329b71..6837d787 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -251,7 +251,10 @@ class World(metaclass=AutoWorldRegister): def fill_slot_data(self) -> Dict[str, Any]: # json of WebHostLib.models.Slot """Fill in the `slot_data` field in the `Connected` network package. This is a way the generator can give custom data to the client. - The client will receive this as JSON in the `Connected` response.""" + The client will receive this as JSON in the `Connected` response. + + The generation does not wait for `generate_output` to complete before calling this. + `threading.Event` can be used if you need to wait for something from `generate_output`.""" return {} def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]): diff --git a/worlds/zillion/__init__.py b/worlds/zillion/__init__.py index 0b9b0e51..069b156c 100644 --- a/worlds/zillion/__init__.py +++ b/worlds/zillion/__init__.py @@ -1,6 +1,7 @@ from collections import deque, Counter from contextlib import redirect_stdout import functools +import threading from typing import Any, Dict, List, Set, Tuple, Optional, cast import os import logging @@ -101,12 +102,15 @@ class ZillionWorld(World): """ my_locations: List[ZillionLocation] = [] """ This is kind of a cache to avoid iterating through all the multiworld locations in logic. """ + slot_data_ready: threading.Event + """ This event is set in `generate_output` when the data is ready for `fill_slot_data` """ def __init__(self, world: MultiWorld, player: int): super().__init__(world, player) self.logger = logging.getLogger("Zillion") self.lsi = ZillionWorld.LogStreamInterface(self.logger) self.zz_system = System() + self.slot_data_ready = threading.Event() def _make_item_maps(self, start_char: Chars) -> None: _id_to_name, _id_to_zz_id, id_to_zz_item = make_id_to_others(start_char) @@ -338,6 +342,7 @@ class ZillionWorld(World): zz_patcher.write_locations(self.zz_system.randomizer.regions, zz_options.start_char, self.zz_system.randomizer.loc_name_2_pretty) + self.slot_data_ready.set() zz_patcher.all_fixes_and_options(zz_options) zz_patcher.set_external_item_interface(zz_options.start_char, zz_options.max_level) zz_patcher.set_multiworld_items(multi_items) @@ -385,6 +390,7 @@ class ZillionWorld(World): assert self.zz_system.randomizer, "didn't get randomizer from generate_early" rescues: Dict[str, Any] = {} + self.slot_data_ready.wait() for i in (0, 1): if i in zz_patcher.rescue_locations: ri = zz_patcher.rescue_locations[i]