Make multiclient/multiserver/tracker keydropshuffle aware
This commit is contained in:
		
							parent
							
								
									0c681c8903
								
							
						
					
					
						commit
						83db79815a
					
				|  | @ -342,7 +342,40 @@ location_table_uw = {"Blind's Hideout - Top": (0x11d, 0x10), | |||
|                      'Ganons Tower - Mini Helmasaur Room - Left': (0x3d, 0x10), | ||||
|                      'Ganons Tower - Mini Helmasaur Room - Right': (0x3d, 0x20), | ||||
|                      'Ganons Tower - Pre-Moldorm Chest': (0x3d, 0x40), | ||||
|                      'Ganons Tower - Validation Chest': (0x4d, 0x10)} | ||||
|                      'Ganons Tower - Validation Chest': (0x4d, 0x10), | ||||
|                      'Hyrule Castle - Map Guard Key Drop': (0x72, 0x400), | ||||
|                      'Hyrule Castle - Boomerang Guard Key Drop': (0x71, 0x400), | ||||
|                      'Hyrule Castle - Key Rat Key Drop': (0x21, 0x400), | ||||
|                      'Hyrule Castle - Big Key Drop': (0x80, 0x400), | ||||
|                      'Eastern Palace - Dark Square Pot Key': (0xba, 0x400), | ||||
|                      'Eastern Palace - Dark Eyegore Key Drop': (0x99, 0x400), | ||||
|                      'Desert Palace - Desert Tiles 1 Pot Key': (0x63, 0x400), | ||||
|                      'Desert Palace - Beamos Hall Pot Key': (0x53, 0x400), | ||||
|                      'Desert Palace - Desert Tiles 2 Pot Key': (0x43, 0x400), | ||||
|                      'Castle Tower - Dark Archer Key Drop': (0xc0, 0x400), | ||||
|                      'Castle Tower - Circle of Pots Key Drop': (0xb0, 0x400), | ||||
|                      'Swamp Palace - Pot Row Pot Key': (0x38, 0x400), | ||||
|                      'Swamp Palace - Trench 1 Pot Key': (0x37, 0x400), | ||||
|                      'Swamp Palace - Hookshot Pot Key': (0x36, 0x400), | ||||
|                      'Swamp Palace - Trench 2 Pot Key': (0x35, 0x400), | ||||
|                      'Swamp Palace - Waterway Pot Key': (0x16, 0x400), | ||||
|                      'Skull Woods - West Lobby Pot Key': (0x56, 0x400), | ||||
|                      'Skull Woods - Spike Corner Key Drop': (0x39, 0x400), | ||||
|                      'Thieves\' Town - Hallway Pot Key': (0xbc, 0x400), | ||||
|                      'Thieves\' Town - Spike Switch Pot Key': (0xab, 0x400), | ||||
|                      'Ice Palace - Jelly Key Drop': (0x0e, 0x400), | ||||
|                      'Ice Palace - Conveyor Key Drop': (0x3e, 0x400), | ||||
|                      'Ice Palace - Hammer Block Key Drop': (0x3f, 0x400), | ||||
|                      'Ice Palace - Many Pots Pot Key': (0x9f, 0x400), | ||||
|                      'Misery Mire - Spikes Pot Key': (0xb3, 0x400), | ||||
|                      'Misery Mire - Fishbone Pot Key': (0xa1, 0x400), | ||||
|                      'Misery Mire - Conveyor Crystal Key Drop': (0xc1, 0x400), | ||||
|                      'Turtle Rock - Pokey 1 Key Drop': (0xb6, 0x400), | ||||
|                      'Turtle Rock - Pokey 2 Key Drop': (0x13, 0x400), | ||||
|                      'Ganons Tower - Conveyor Cross Pot Key': (0x8b, 0x400), | ||||
|                      'Ganons Tower - Double Switch Pot Key': (0x9b, 0x400), | ||||
|                      'Ganons Tower - Conveyor Star Pits Pot Key': (0x7b, 0x400), | ||||
|                      'Ganons Tower - Mini Helmasaur Key Drop': (0x3d, 0x400)} | ||||
| location_table_npc = {'Mushroom': 0x1000, | ||||
|                       'King Zora': 0x2, | ||||
|                       'Sahasrahla': 0x10, | ||||
|  | @ -822,7 +855,7 @@ async def process_server_cmd(ctx: Context, cmd, args): | |||
|         ctx.player_names = {p: n for p, n in args[1]} | ||||
|         msgs = [] | ||||
|         if ctx.locations_checked: | ||||
|             msgs.append(['LocationChecks', [Regions.location_table[loc][0] for loc in ctx.locations_checked]]) | ||||
|             msgs.append(['LocationChecks', [Regions.lookup_name_to_id[loc] for loc in ctx.locations_checked]]) | ||||
|         if ctx.locations_scouted: | ||||
|             msgs.append(['LocationScouts', list(ctx.locations_scouted)]) | ||||
|         if msgs: | ||||
|  | @ -837,7 +870,7 @@ async def process_server_cmd(ctx: Context, cmd, args): | |||
|         elif start_index != len(ctx.items_received): | ||||
|             sync_msg = [['Sync']] | ||||
|             if ctx.locations_checked: | ||||
|                 sync_msg.append(['LocationChecks', [Regions.location_table[loc][0] for loc in ctx.locations_checked]]) | ||||
|                 sync_msg.append(['LocationChecks', [Regions.lookup_name_to_id[loc] for loc in ctx.locations_checked]]) | ||||
|             await ctx.send_msgs(sync_msg) | ||||
|         if start_index == len(ctx.items_received): | ||||
|             for item in items: | ||||
|  | @ -1014,6 +1047,11 @@ class ClientCommandProcessor(CommandProcessor): | |||
|                 self.output('Missing: ' + location) | ||||
|                 count += 1 | ||||
| 
 | ||||
|         for location in [k for k, v in Regions.key_drop_data.items()]: | ||||
|             if location not in self.ctx.locations_checked: | ||||
|                 self.output('Missing: ' + location) | ||||
|                 count += 1 | ||||
| 
 | ||||
|         if count: | ||||
|             self.output(f"Found {count} missing location checks") | ||||
|         else: | ||||
|  | @ -1077,11 +1115,14 @@ async def track_locations(ctx : Context, roomid, roomdata): | |||
|         ctx.locations_checked.add(location) | ||||
|         ctx.ui_node.log_info("New check: %s (%d/216)" % (location, len(ctx.locations_checked))) | ||||
|         ctx.ui_node.send_location_check(ctx, location) | ||||
|         new_locations.append(Regions.location_table[location][0]) | ||||
|         new_locations.append(Regions.lookup_name_to_id[location]) | ||||
| 
 | ||||
|     for location, (loc_roomid, loc_mask) in location_table_uw.items(): | ||||
|         if location not in ctx.locations_checked and loc_roomid == roomid and (roomdata << 4) & loc_mask != 0: | ||||
|             new_check(location) | ||||
|         try: | ||||
|             if location not in ctx.locations_checked and loc_roomid == roomid and (roomdata << 4) & loc_mask != 0: | ||||
|                 new_check(location) | ||||
|         except Exception as e: | ||||
|             ctx.ui_node.log_info(f"Exception: {e}") | ||||
| 
 | ||||
|     uw_begin = 0x129 | ||||
|     uw_end = 0 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ import Utils | |||
| from Utils import get_item_name_from_id, get_location_name_from_address, ReceivedItem, _version_tuple | ||||
| from NetUtils import Node, Endpoint | ||||
| 
 | ||||
| console_names = frozenset(set(Items.item_table) | set(Regions.location_table) | set(Items.item_name_groups)) | ||||
| console_names = frozenset(set(Items.item_table) | set(Regions.location_table) | set(Items.item_name_groups) | set(Regions.key_drop_data)) | ||||
| 
 | ||||
| CLIENT_PLAYING = 0 | ||||
| CLIENT_GOAL = 1 | ||||
|  | @ -439,6 +439,7 @@ def send_new_items(ctx: Context): | |||
| 
 | ||||
| def forfeit_player(ctx: Context, team: int, slot: int): | ||||
|     all_locations = {values[0] for values in Regions.location_table.values() if type(values[0]) is int} | ||||
|     all_locations.update({values[1] for values in Regions.key_drop_data.values()}) | ||||
|     ctx.notify_all("%s (Team #%d) has forfeited" % (ctx.player_names[(team, slot)], team + 1)) | ||||
|     register_location_checks(ctx, team, slot, all_locations) | ||||
| 
 | ||||
|  | @ -514,7 +515,7 @@ def collect_hints(ctx: Context, team: int, slot: int, item: str) -> typing.List[ | |||
| 
 | ||||
| def collect_hints_location(ctx: Context, team: int, slot: int, location: str) -> typing.List[Utils.Hint]: | ||||
|     hints = [] | ||||
|     seeked_location = Regions.location_table[location][0] | ||||
|     seeked_location = Regions.lookup_name_to_id[location] | ||||
|     for check, result in ctx.locations.items(): | ||||
|         location_id, finding_player = check | ||||
|         if finding_player == slot and location_id == seeked_location: | ||||
|  |  | |||
							
								
								
									
										63
									
								
								Regions.py
								
								
								
								
							
							
						
						
									
										63
									
								
								Regions.py
								
								
								
								
							|  | @ -397,6 +397,42 @@ shop_table = { | |||
|     'Capacity Upgrade': (0x0115, ShopType.UpgradeShop, 0x04, True, True, [('Bomb Upgrade (+5)', 100, 7), ('Arrow Upgrade (+5)', 100, 7)]) | ||||
| } | ||||
| 
 | ||||
| key_drop_data = { | ||||
|     'Hyrule Castle - Map Guard Key Drop': [0x140036, 0x140037], | ||||
|     'Hyrule Castle - Boomerang Guard Key Drop': [0x140033, 0x140034], | ||||
|     'Hyrule Castle - Key Rat Key Drop': [0x14000c, 0x14000d], | ||||
|     'Hyrule Castle - Big Key Drop': [0x14003c, 0x14003d], | ||||
|     'Eastern Palace - Dark Square Pot Key': [0x14005a, 0x14005b], | ||||
|     'Eastern Palace - Dark Eyegore Key Drop': [0x140048, 0x140049], | ||||
|     'Desert Palace - Desert Tiles 1 Pot Key': [0x140030, 0x140031], | ||||
|     'Desert Palace - Beamos Hall Pot Key': [0x14002a, 0x14002b], | ||||
|     'Desert Palace - Desert Tiles 2 Pot Key': [0x140027, 0x140028], | ||||
|     'Castle Tower - Dark Archer Key Drop': [0x140060, 0x140061], | ||||
|     'Castle Tower - Circle of Pots Key Drop': [0x140051, 0x140052], | ||||
|     'Swamp Palace - Pot Row Pot Key': [0x140018, 0x140019], | ||||
|     'Swamp Palace - Trench 1 Pot Key': [0x140015, 0x140016], | ||||
|     'Swamp Palace - Hookshot Pot Key': [0x140012, 0x140013], | ||||
|     'Swamp Palace - Trench 2 Pot Key': [0x14000f, 0x140010], | ||||
|     'Swamp Palace - Waterway Pot Key': [0x140009, 0x14000a], | ||||
|     'Skull Woods - West Lobby Pot Key': [0x14002d, 0x14002e], | ||||
|     'Skull Woods - Spike Corner Key Drop': [0x14001b, 0x14001c], | ||||
|     'Thieves\' Town - Hallway Pot Key': [0x14005d, 0x14005e], | ||||
|     'Thieves\' Town - Spike Switch Pot Key': [0x14004e, 0x14004f], | ||||
|     'Ice Palace - Jelly Key Drop': [0x140003, 0x140004], | ||||
|     'Ice Palace - Conveyor Key Drop': [0x140021, 0x140022], | ||||
|     'Ice Palace - Hammer Block Key Drop': [0x140024, 0x140025], | ||||
|     'Ice Palace - Many Pots Pot Key': [0x140045, 0x140046], | ||||
|     'Misery Mire - Spikes Pot Key': [0x140054, 0x140055], | ||||
|     'Misery Mire - Fishbone Pot Key': [0x14004b, 0x14004c], | ||||
|     'Misery Mire - Conveyor Crystal Key Drop': [0x140063, 0x140064], | ||||
|     'Turtle Rock - Pokey 1 Key Drop': [0x140057, 0x140058], | ||||
|     'Turtle Rock - Pokey 2 Key Drop': [0x140006, 0x140007], | ||||
|     'Ganons Tower - Conveyor Cross Pot Key': [0x14003f, 0x140040], | ||||
|     'Ganons Tower - Double Switch Pot Key': [0x140042, 0x140043], | ||||
|     'Ganons Tower - Conveyor Star Pits Pot Key': [0x140039, 0x14003a], | ||||
|     'Ganons Tower - Mini Helmasaur Key Drop': [0x14001e, 0x14001f] | ||||
| } | ||||
| 
 | ||||
| location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), | ||||
|                   'Bottle Merchant': (0x2eb18, 0x186339, False, 'with a merchant'), | ||||
|                   'Flute Spot': (0x18014a, 0x18633d, False, 'underground'), | ||||
|  | @ -640,7 +676,9 @@ location_table = {'Mushroom': (0x180013, 0x186338, False, 'in the woods'), | |||
|                       [0x120A7, 0x53F24, 0x53F25, 0x18005C, 0x180079, 0xC708], None, True, 'Turtle Rock')} | ||||
| 
 | ||||
| lookup_id_to_name = {data[0]: name for name, data in location_table.items() if type(data[0]) == int} | ||||
| lookup_id_to_name[-1] = "cheat console" | ||||
| lookup_id_to_name = {**lookup_id_to_name, **{data[1]: name for name, data in key_drop_data.items()}, -1: "cheat console"} | ||||
| lookup_name_to_id = {name: data[0] for name, data in location_table.items() if type(data[0]) == int} | ||||
| lookup_name_to_id = {**lookup_name_to_id, **{name: data[1] for name, data in key_drop_data.items()}, "cheat console": -1} | ||||
| 
 | ||||
| lookup_vanilla_location_to_entrance = {1572883: 'Kings Grave Inner Rocks', 191256: 'Kings Grave Inner Rocks', | ||||
|                                        1573194: 'Kings Grave Inner Rocks', 1573189: 'Kings Grave Inner Rocks', | ||||
|  | @ -745,7 +783,28 @@ lookup_vanilla_location_to_entrance = {1572883: 'Kings Grave Inner Rocks', 19125 | |||
|                                        60103: 'Ganons Tower', 60106: 'Ganons Tower', 60109: 'Ganons Tower', | ||||
|                                        60127: 'Ganons Tower', 60118: 'Ganons Tower', 60148: 'Ganons Tower', | ||||
|                                        60151: 'Ganons Tower', 60145: 'Ganons Tower', 60157: 'Ganons Tower', | ||||
|                                        60160: 'Ganons Tower', 60163: 'Ganons Tower', 60166: 'Ganons Tower'} | ||||
|                                        60160: 'Ganons Tower', 60163: 'Ganons Tower', 60166: 'Ganons Tower', | ||||
|                                        0x140037: 'Hyrule Castle Entrance (South)', | ||||
|                                        0x140034: 'Hyrule Castle Entrance (South)', | ||||
|                                        0x14000d: 'Hyrule Castle Entrance (South)', | ||||
|                                        0x14003d: 'Hyrule Castle Entrance (South)', | ||||
|                                        0x14005b: 'Eastern Palace', 0x140049: 'Eastern Palace', | ||||
|                                        0x140031: 'Desert Palace Entrance (North)', | ||||
|                                        0x14002b: 'Desert Palace Entrance (North)', | ||||
|                                        0x140028: 'Desert Palace Entrance (North)', | ||||
|                                        0x140061: 'Agahnims Tower', 0x140052: 'Agahnims Tower', | ||||
|                                        0x140019: 'Swamp Palace', 0x140016: 'Swamp Palace', 0x140013: 'Swamp Palace', | ||||
|                                        0x140010: 'Swamp Palace', 0x14000a: 'Swamp Palace', | ||||
|                                        0x14002e: 'Skull Woods Second Section Door (East)', | ||||
|                                        0x14001c: 'Skull Woods Final Section', | ||||
|                                        0x14005e: 'Thieves Town', 0x14004f: 'Thieves Town', | ||||
|                                        0x140004: 'Ice Palace', 0x140022: 'Ice Palace', | ||||
|                                        0x140025: 'Ice Palace', 0x140046: 'Ice Palace', | ||||
|                                        0x140055: 'Misery Mire', 0x14004c: 'Misery Mire', | ||||
|                                        0x140064: 'Misery Mire', | ||||
|                                        0x140058: 'Turtle Rock', 0x140007: 'Dark Death Mountain Ledge (West)', | ||||
|                                        0x140040: 'Ganons Tower', 0x140043: 'Ganons Tower', | ||||
|                                        0x14003a: 'Ganons Tower', 0x14001f: 'Ganons Tower'} | ||||
| 
 | ||||
| lookup_prizes = {location for location in location_table if location.endswith(" - Prize")} | ||||
| lookup_boss_drops = {location for location in location_table if location.endswith(" - Boss")} | ||||
|  | @ -180,6 +180,25 @@ default_locations = { | |||
|                      60121, 60124, 60127, 1573217, 60130, 60133, 60136, 60139, 60142, 60145, 60148, 60151, 60157}, | ||||
|     'Total': set()} | ||||
| 
 | ||||
| key_only_locations = { | ||||
|     'Light World': set(), | ||||
|     'Dark World': set(), | ||||
|     'Desert Palace': {0x140031, 0x14002b, 0x140061, 0x140028}, | ||||
|     'Eastern Palace': {0x14005b, 0x140049}, | ||||
|     'Hyrule Castle': {0x140037, 0x140034, 0x14000d, 0x14003d}, | ||||
|     'Agahnims Tower': {0x140061, 0x140052}, | ||||
|     'Tower of Hera': set(), | ||||
|     'Swamp Palace': {0x140019, 0x140016, 0x140013, 0x140010, 0x14000a}, | ||||
|     'Thieves Town': {0x14005e, 0x14004f}, | ||||
|     'Skull Woods': {0x14002e, 0x14001c}, | ||||
|     'Ice Palace': {0x140004, 0x140022, 0x140025, 0x140046}, | ||||
|     'Misery Mire': {0x140055, 0x14004c, 0x140064}, | ||||
|     'Turtle Rock': {0x140058, 0x140007}, | ||||
|     'Palace of Darkness': set(), | ||||
|     'Ganons Tower': {0x140040, 0x140043, 0x14003a, 0x14001f}, | ||||
|     'Total': set() | ||||
| } | ||||
| 
 | ||||
| key_locations = {"Desert Palace", "Eastern Palace", "Hyrule Castle", "Agahnims Tower", "Tower of Hera", "Swamp Palace", | ||||
|                  "Thieves Town", "Skull Woods", "Ice Palace", "Misery Mire", "Turtle Rock", "Palace of Darkness", | ||||
|                  "Ganons Tower"} | ||||
|  | @ -191,6 +210,10 @@ for area, locations in default_locations.items(): | |||
|     for location in locations: | ||||
|         location_to_area[location] = area | ||||
| 
 | ||||
| for area, locations in key_only_locations.items(): | ||||
|     for location in locations: | ||||
|         location_to_area[location] = area | ||||
| 
 | ||||
| checks_in_area = {area: len(checks) for area, checks in default_locations.items()} | ||||
| checks_in_area["Total"] = 216 | ||||
| 
 | ||||
|  | @ -244,11 +267,16 @@ def get_static_room_data(room: Room): | |||
|     # in > 100 players this can take a bit of time and is the main reason for the cache | ||||
|     locations = {tuple(k): tuple(v) for k, v in multidata['locations']} | ||||
|     names = multidata["names"] | ||||
|     seed_checks_in_area = checks_in_area.copy() | ||||
| 
 | ||||
|     use_door_tracker = False | ||||
|     if "tags" in multidata: | ||||
|         use_door_tracker = "DR" in multidata["tags"] | ||||
|     result = locations, names, use_door_tracker | ||||
|     if use_door_tracker: | ||||
|         for area, checks in key_only_locations.items(): | ||||
|             seed_checks_in_area[area] += len(checks) | ||||
|         seed_checks_in_area["Total"] = 249 | ||||
|     result = locations, names, use_door_tracker, seed_checks_in_area | ||||
|     _multidata_cache[room.seed.id] = result | ||||
|     return result | ||||
| 
 | ||||
|  | @ -259,7 +287,7 @@ def get_tracker(tracker: UUID): | |||
|     room = Room.get(tracker=tracker) | ||||
|     if not room: | ||||
|         abort(404) | ||||
|     locations, names, use_door_tracker = get_static_room_data(room) | ||||
|     locations, names, use_door_tracker, seed_checks_in_area = get_static_room_data(room) | ||||
| 
 | ||||
|     inventory = {teamnumber: {playernumber: collections.Counter() for playernumber in range(1, len(team) + 1)} | ||||
|                  for teamnumber, team in enumerate(names)} | ||||
|  | @ -280,6 +308,9 @@ def get_tracker(tracker: UUID): | |||
|             for item_id in precollected: | ||||
|                 attribute_item(inventory, team, player, item_id) | ||||
|         for location in locations_checked: | ||||
|             if (location, player) not in locations or location not in location_to_area: | ||||
|                 continue | ||||
| 
 | ||||
|             item, recipient = locations[location, player] | ||||
|             attribute_item(inventory, team, recipient, item) | ||||
|             checks_done[team][player][location_to_area[location]] += 1 | ||||
|  | @ -311,7 +342,7 @@ def get_tracker(tracker: UUID): | |||
|                            lookup_id_to_name=Items.lookup_id_to_name, player_names=player_names, | ||||
|                            tracking_names=tracking_names, tracking_ids=tracking_ids, room=room, icons=icons, | ||||
|                            multi_items=multi_items, checks_done=checks_done, ordered_areas=ordered_areas, | ||||
|                            checks_in_area=checks_in_area, activity_timers=activity_timers, | ||||
|                            checks_in_area=seed_checks_in_area, activity_timers=activity_timers, | ||||
|                            key_locations=key_locations, small_key_ids=small_key_ids, big_key_ids=big_key_ids, | ||||
|                            video=video, big_key_locations=key_locations if use_door_tracker else big_key_locations, | ||||
|                            hints=hints, long_player_names = long_player_names) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue