Zillion: fix invalid slot data from race condition

This commit is contained in:
beauxq 2022-12-09 17:54:29 -08:00 committed by Fabian Dill
parent c3fe341736
commit b7d46004e2
3 changed files with 14 additions and 1 deletions

View File

@ -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 = {

View File

@ -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]]):

View File

@ -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]