Hints now contain ER info
This commit is contained in:
parent
11678fa20b
commit
b2e20be077
|
@ -3957,3 +3957,11 @@ exit_ids = {'Links House Exit': (0x01, 0x00),
|
||||||
'Skull Woods First Section (Right)': 0x78,
|
'Skull Woods First Section (Right)': 0x78,
|
||||||
'Skull Woods First Section (Top)': 0x76,
|
'Skull Woods First Section (Top)': 0x76,
|
||||||
'Pyramid': 0x7B}
|
'Pyramid': 0x7B}
|
||||||
|
|
||||||
|
exit_id_to_name = {}
|
||||||
|
for name, addresses in exit_ids.items():
|
||||||
|
if type(addresses) == int:
|
||||||
|
exit_id_to_name[addresses] = name
|
||||||
|
else:
|
||||||
|
for address in addresses:
|
||||||
|
exit_id_to_name[address] = name
|
||||||
|
|
21
Main.py
21
Main.py
|
@ -236,6 +236,24 @@ def main(args, seed=None):
|
||||||
for future in futures:
|
for future in futures:
|
||||||
rom_name = future.result()
|
rom_name = future.result()
|
||||||
rom_names.append(rom_name)
|
rom_names.append(rom_name)
|
||||||
|
|
||||||
|
def get_entrance_to_region(region: Region):
|
||||||
|
for entrance in region.entrances:
|
||||||
|
if entrance.parent_region.type in (RegionType.DarkWorld, RegionType.LightWorld):
|
||||||
|
return entrance
|
||||||
|
for entrance in region.entrances: # BFS might be better here, trying DFS for now.
|
||||||
|
return get_entrance_to_region(entrance.parent_region)
|
||||||
|
|
||||||
|
# collect ER hint info
|
||||||
|
er_hint_data = {player: {} for player in range(1, world.players + 1) if world.shuffle[player] != "vanilla"}
|
||||||
|
from Regions import RegionType
|
||||||
|
for region in world.regions:
|
||||||
|
if region.player in er_hint_data and region.locations:
|
||||||
|
main_entrance = get_entrance_to_region(region)
|
||||||
|
for location in region.locations:
|
||||||
|
if type(location.address) == int: # skips events and crystals
|
||||||
|
er_hint_data[region.player][location.address] = main_entrance.name
|
||||||
|
|
||||||
multidata = zlib.compress(json.dumps({"names": parsed_names,
|
multidata = zlib.compress(json.dumps({"names": parsed_names,
|
||||||
"roms": rom_names,
|
"roms": rom_names,
|
||||||
"remote_items": [player for player in range(1, world.players + 1) if
|
"remote_items": [player for player in range(1, world.players + 1) if
|
||||||
|
@ -244,7 +262,8 @@ def main(args, seed=None):
|
||||||
(location.item.code, location.item.player))
|
(location.item.code, location.item.player))
|
||||||
for location in world.get_filled_locations() if
|
for location in world.get_filled_locations() if
|
||||||
type(location.address) is int],
|
type(location.address) is int],
|
||||||
"server_options": get_options()["server_options"]
|
"server_options": get_options()["server_options"],
|
||||||
|
"er_hint_data": er_hint_data,
|
||||||
}).encode("utf-8"), 9)
|
}).encode("utf-8"), 9)
|
||||||
if args.jsonout:
|
if args.jsonout:
|
||||||
jsonout["multidata"] = list(multidata)
|
jsonout["multidata"] = list(multidata)
|
||||||
|
|
|
@ -764,9 +764,11 @@ async def process_server_cmd(ctx : Context, cmd, args):
|
||||||
'yellow' if hint.finding_player != ctx.slot else 'magenta')
|
'yellow' if hint.finding_player != ctx.slot else 'magenta')
|
||||||
player_recvd = color(ctx.player_names[hint.receiving_player],
|
player_recvd = color(ctx.player_names[hint.receiving_player],
|
||||||
'yellow' if hint.receiving_player != ctx.slot else 'magenta')
|
'yellow' if hint.receiving_player != ctx.slot else 'magenta')
|
||||||
logging.info(f"[Hint]: {player_recvd}'s {item} can be found "
|
text = f"[Hint]: {player_recvd}'s {item} can be found " \
|
||||||
f"at {get_location_name_from_address(hint.location)} in {player_find}'s World." +
|
f"at {color(get_location_name_from_address(hint.location), 'blue_bg')} in {player_find}'s World"
|
||||||
(" (found)" if hint.found else ""))
|
if hint.entrance:
|
||||||
|
text += " at " + color(hint.entrance, 'cyan_bg')
|
||||||
|
logging.info(text + (". (found)" if hint.found else "."))
|
||||||
elif cmd == "AliasUpdate":
|
elif cmd == "AliasUpdate":
|
||||||
ctx.player_names = {p: n for p, n in args}
|
ctx.player_names = {p: n for p, n in args}
|
||||||
elif cmd == 'Print':
|
elif cmd == 'Print':
|
||||||
|
|
|
@ -88,6 +88,7 @@ class Context:
|
||||||
self.running = True
|
self.running = True
|
||||||
self.client_activity_timers = {}
|
self.client_activity_timers = {}
|
||||||
self.client_game_state: typing.Dict[typing.Tuple[int, int], int] = collections.defaultdict(int)
|
self.client_game_state: typing.Dict[typing.Tuple[int, int], int] = collections.defaultdict(int)
|
||||||
|
self.er_hint_data: typing.Dict[int, typing.Dict[int, str]] = {}
|
||||||
self.commandprocessor = ServerCommandProcessor(self)
|
self.commandprocessor = ServerCommandProcessor(self)
|
||||||
|
|
||||||
def get_save(self) -> dict:
|
def get_save(self) -> dict:
|
||||||
|
@ -198,14 +199,14 @@ def notify_hints(ctx: Context, team: int, hints: typing.List[Utils.Hint]):
|
||||||
texts = [['Print', format_hint(ctx, team, hint)] for hint in hints]
|
texts = [['Print', format_hint(ctx, team, hint)] for hint in hints]
|
||||||
for _, text in texts:
|
for _, text in texts:
|
||||||
logging.info("Notice (Team #%d): %s" % (team + 1, text))
|
logging.info("Notice (Team #%d): %s" % (team + 1, text))
|
||||||
|
texts = json.dumps(texts)
|
||||||
for client in ctx.clients:
|
for client in ctx.clients:
|
||||||
if client.auth and client.team == team:
|
if client.auth and client.team == team:
|
||||||
if "Berserker" in client.tags:
|
if "Berserker" in client.tags and client.version >= [2, 2, 1]:
|
||||||
payload = cmd
|
payload = cmd
|
||||||
asyncio.create_task(send_json_msgs(client, payload))
|
|
||||||
else:
|
else:
|
||||||
payload = texts
|
payload = texts
|
||||||
asyncio.create_task(send_msgs(client, payload))
|
asyncio.create_task(send_json_msgs(client, payload))
|
||||||
|
|
||||||
|
|
||||||
def update_aliases(ctx: Context, team: int, client: typing.Optional[Client] = None):
|
def update_aliases(ctx: Context, team: int, client: typing.Optional[Client] = None):
|
||||||
|
@ -383,7 +384,11 @@ def collect_hints(ctx: Context, team: int, slot: int, item: str) -> typing.List[
|
||||||
if receiving_player == slot and item_id == seeked_item_id:
|
if receiving_player == slot and item_id == seeked_item_id:
|
||||||
location_id, finding_player = check
|
location_id, finding_player = check
|
||||||
found = location_id in ctx.location_checks[team, finding_player]
|
found = location_id in ctx.location_checks[team, finding_player]
|
||||||
hints.append(Utils.Hint(receiving_player, finding_player, location_id, item_id, found))
|
entrance = ""
|
||||||
|
if finding_player in ctx.er_hint_data:
|
||||||
|
if location_id in ctx.er_hint_data[finding_player]:
|
||||||
|
entrance = ctx.er_hint_data[finding_player][location_id]
|
||||||
|
hints.append(Utils.Hint(receiving_player, finding_player, location_id, item_id, found, entrance))
|
||||||
|
|
||||||
return hints
|
return hints
|
||||||
|
|
||||||
|
@ -396,17 +401,24 @@ def collect_hints_location(ctx: Context, team: int, slot: int, location: str) ->
|
||||||
if finding_player == slot and location_id == seeked_location:
|
if finding_player == slot and location_id == seeked_location:
|
||||||
item_id, receiving_player = result
|
item_id, receiving_player = result
|
||||||
found = location_id in ctx.location_checks[team, finding_player]
|
found = location_id in ctx.location_checks[team, finding_player]
|
||||||
hints.append(Utils.Hint(receiving_player, finding_player, location_id, item_id, found))
|
entrance = ""
|
||||||
break # each location has 1 item
|
if finding_player in ctx.er_hint_data:
|
||||||
|
if location_id in ctx.er_hint_data[finding_player]:
|
||||||
|
entrance = ctx.er_hint_data[finding_player][location_id]
|
||||||
|
hints.append(Utils.Hint(receiving_player, finding_player, location_id, item_id, found, entrance))
|
||||||
|
break # each location has 1 item
|
||||||
return hints
|
return hints
|
||||||
|
|
||||||
|
|
||||||
def format_hint(ctx: Context, team: int, hint: Utils.Hint) -> str:
|
def format_hint(ctx: Context, team: int, hint: Utils.Hint) -> str:
|
||||||
return f"[Hint]: {ctx.player_names[team, hint.receiving_player]}'s " \
|
text = f"[Hint]: {ctx.player_names[team, hint.receiving_player]}'s " \
|
||||||
f"{Items.lookup_id_to_name[hint.item]} can be found " \
|
f"{Items.lookup_id_to_name[hint.item]} can be found " \
|
||||||
f"at {get_location_name_from_address(hint.location)} " \
|
f"at {get_location_name_from_address(hint.location)} " \
|
||||||
f"in {ctx.player_names[team, hint.finding_player]}'s World." \
|
f"in {ctx.player_names[team, hint.finding_player]}'s World"
|
||||||
+ (" (found)" if hint.found else "")
|
|
||||||
|
if hint.entrance:
|
||||||
|
text += f" at {hint.entrance}"
|
||||||
|
return text + (". (found)" if hint.found else ".")
|
||||||
|
|
||||||
|
|
||||||
def get_intended_text(input_text: str, possible_answers: typing.Iterable[str]= console_names) -> typing.Tuple[str, bool, str]:
|
def get_intended_text(input_text: str, possible_answers: typing.Iterable[str]= console_names) -> typing.Tuple[str, bool, str]:
|
||||||
|
@ -1051,6 +1063,9 @@ async def main(args: argparse.Namespace):
|
||||||
ctx.rom_names = {tuple(rom): (team, slot) for slot, team, rom in jsonobj['roms']}
|
ctx.rom_names = {tuple(rom): (team, slot) for slot, team, rom in jsonobj['roms']}
|
||||||
ctx.remote_items = set(jsonobj['remote_items'])
|
ctx.remote_items = set(jsonobj['remote_items'])
|
||||||
ctx.locations = {tuple(k): tuple(v) for k, v in jsonobj['locations']}
|
ctx.locations = {tuple(k): tuple(v) for k, v in jsonobj['locations']}
|
||||||
|
if "er_hint_data" in jsonobj:
|
||||||
|
ctx.er_hint_data = {int(player): {int(address): name for address, name in loc_data.items()}
|
||||||
|
for player, loc_data in jsonobj["er_hint_data"].items()}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception('Failed to read multiworld data (%s)' % e)
|
logging.exception('Failed to read multiworld data (%s)' % e)
|
||||||
return
|
return
|
||||||
|
|
10
Utils.py
10
Utils.py
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
__version__ = "2.2.0"
|
__version__ = "2.2.1"
|
||||||
_version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
|
_version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -159,17 +159,21 @@ class Hint(typing.NamedTuple):
|
||||||
location: int
|
location: int
|
||||||
item: int
|
item: int
|
||||||
found: bool
|
found: bool
|
||||||
|
entrance: str = ""
|
||||||
|
|
||||||
def re_check(self, ctx, team) -> Hint:
|
def re_check(self, ctx, team) -> Hint:
|
||||||
if self.found:
|
if self.found:
|
||||||
return self
|
return self
|
||||||
found = self.location in ctx.location_checks[team, self.finding_player]
|
found = self.location in ctx.location_checks[team, self.finding_player]
|
||||||
if found:
|
if found:
|
||||||
return Hint(self.receiving_player, self.finding_player, self.location, self.item, found)
|
return Hint(self.receiving_player, self.finding_player, self.location, self.item, found, self.entrance)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def as_legacy(self) -> tuple:
|
||||||
|
return self.receiving_player, self.finding_player, self.location, self.item, self.found
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.receiving_player, self.finding_player, self.location, self.item))
|
return hash((self.receiving_player, self.finding_player, self.location, self.item, self.entrance))
|
||||||
|
|
||||||
def get_public_ipv4() -> str:
|
def get_public_ipv4() -> str:
|
||||||
import socket
|
import socket
|
||||||
|
|
Loading…
Reference in New Issue