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 (Top)': 0x76,
 | 
			
		||||
            '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:
 | 
			
		||||
            rom_name = future.result()
 | 
			
		||||
            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,
 | 
			
		||||
                                              "roms": rom_names,
 | 
			
		||||
                                              "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))
 | 
			
		||||
                                                            for location in world.get_filled_locations() if
 | 
			
		||||
                                                            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)
 | 
			
		||||
        if args.jsonout:
 | 
			
		||||
            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')
 | 
			
		||||
            player_recvd = color(ctx.player_names[hint.receiving_player],
 | 
			
		||||
                                 'yellow' if hint.receiving_player != ctx.slot else 'magenta')
 | 
			
		||||
            logging.info(f"[Hint]: {player_recvd}'s {item} can be found "
 | 
			
		||||
                         f"at {get_location_name_from_address(hint.location)} in {player_find}'s World." +
 | 
			
		||||
                         (" (found)" if hint.found else ""))
 | 
			
		||||
            text = f"[Hint]: {player_recvd}'s {item} can be found " \
 | 
			
		||||
                   f"at {color(get_location_name_from_address(hint.location), 'blue_bg')} in {player_find}'s World"
 | 
			
		||||
            if hint.entrance:
 | 
			
		||||
                text += " at " + color(hint.entrance, 'cyan_bg')
 | 
			
		||||
            logging.info(text + (". (found)" if hint.found else "."))
 | 
			
		||||
    elif cmd == "AliasUpdate":
 | 
			
		||||
        ctx.player_names = {p: n for p, n in args}
 | 
			
		||||
    elif cmd == 'Print':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,6 +88,7 @@ class Context:
 | 
			
		|||
        self.running = True
 | 
			
		||||
        self.client_activity_timers = {}
 | 
			
		||||
        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)
 | 
			
		||||
 | 
			
		||||
    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]
 | 
			
		||||
    for _, text in texts:
 | 
			
		||||
        logging.info("Notice (Team #%d): %s" % (team + 1, text))
 | 
			
		||||
    texts = json.dumps(texts)
 | 
			
		||||
    for client in ctx.clients:
 | 
			
		||||
        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
 | 
			
		||||
                asyncio.create_task(send_json_msgs(client, payload))
 | 
			
		||||
            else:
 | 
			
		||||
                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):
 | 
			
		||||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
            location_id, finding_player = check
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
            item_id, receiving_player = result
 | 
			
		||||
            found = location_id in ctx.location_checks[team, finding_player]
 | 
			
		||||
            hints.append(Utils.Hint(receiving_player, finding_player, location_id, item_id, found))
 | 
			
		||||
            break # each location has 1 item
 | 
			
		||||
            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))
 | 
			
		||||
            break  # each location has 1 item
 | 
			
		||||
    return hints
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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"at {get_location_name_from_address(hint.location)} " \
 | 
			
		||||
           f"in {ctx.player_names[team, hint.finding_player]}'s World." \
 | 
			
		||||
           + (" (found)" if hint.found else "")
 | 
			
		||||
           f"in {ctx.player_names[team, hint.finding_player]}'s World"
 | 
			
		||||
 | 
			
		||||
    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]:
 | 
			
		||||
| 
						 | 
				
			
			@ -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.remote_items = set(jsonobj['remote_items'])
 | 
			
		||||
            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:
 | 
			
		||||
        logging.exception('Failed to read multiworld data (%s)' % e)
 | 
			
		||||
        return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								Utils.py
								
								
								
								
							
							
						
						
									
										10
									
								
								Utils.py
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
from __future__ import annotations
 | 
			
		||||
 | 
			
		||||
__version__ = "2.2.0"
 | 
			
		||||
__version__ = "2.2.1"
 | 
			
		||||
_version_tuple = tuple(int(piece, 10) for piece in __version__.split("."))
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
| 
						 | 
				
			
			@ -159,17 +159,21 @@ class Hint(typing.NamedTuple):
 | 
			
		|||
    location: int
 | 
			
		||||
    item: int
 | 
			
		||||
    found: bool
 | 
			
		||||
    entrance: str = ""
 | 
			
		||||
 | 
			
		||||
    def re_check(self, ctx, team) -> Hint:
 | 
			
		||||
        if self.found:
 | 
			
		||||
            return self
 | 
			
		||||
        found = self.location in ctx.location_checks[team, self.finding_player]
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
    def as_legacy(self) -> tuple:
 | 
			
		||||
        return self.receiving_player, self.finding_player, self.location, self.item, self.found
 | 
			
		||||
 | 
			
		||||
    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:
 | 
			
		||||
    import socket
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue