Add further safeties to sending of location checks.

This safety is able to be turned off, but has to be done so on EVERY connection explicitly.
This commit is contained in:
CaitSith2 2020-10-27 16:24:21 -07:00
parent 5c403086d9
commit 66894dbd86
2 changed files with 26 additions and 18 deletions

View File

@ -85,6 +85,7 @@ class Context():
self.slot = None self.slot = None
self.player_names: typing.Dict[int: str] = {} self.player_names: typing.Dict[int: str] = {}
self.locations_checked = set() self.locations_checked = set()
self.unsafe_locations_checked = set()
self.locations_scouted = set() self.locations_scouted = set()
self.items_received = [] self.items_received = []
self.items_missing = [] self.items_missing = []
@ -863,10 +864,11 @@ async def process_server_cmd(ctx: Context, cmd, args):
await ctx.send_msgs(msgs) await ctx.send_msgs(msgs)
if ctx.finished_game: if ctx.finished_game:
await send_finished_game(ctx) await send_finished_game(ctx)
ctx.items_missing = [] # Get the server side view of missing as of time of connecting. ctx.items_missing = args[2] if len(args) >= 3 else [] # Get the server side view of missing as of time of connecting.
# This list is used to only send to the server what is reported as ACTUALLY Missing. # This list is used to only send to the server what is reported as ACTUALLY Missing.
# This also serves to allow an easy visual of what locations were already checked previously # This also serves to allow an easy visual of what locations were already checked previously
# when /missing is used for the client side view of what is missing. # when /missing is used for the client side view of what is missing.
if not ctx.items_missing:
asyncio.create_task(ctx.send_msgs([['Say', '!missing']])) asyncio.create_task(ctx.send_msgs([['Say', '!missing']]))
elif cmd == 'ReceivedItems': elif cmd == 'ReceivedItems':
@ -1136,15 +1138,13 @@ async def track_locations(ctx : Context, roomid, roomdata):
new_locations = [] new_locations = []
def new_check(location): def new_check(location):
ctx.locations_checked.add(location) ctx.unsafe_locations_checked.add(location)
ctx.ui_node.log_info("New check: %s (%d/216)" % (location, len(ctx.locations_checked))) ctx.ui_node.log_info("New check: %s (%d/216)" % (location, len(ctx.unsafe_locations_checked)))
ctx.ui_node.send_location_check(ctx, location) ctx.ui_node.send_location_check(ctx, location)
if location in ctx.items_missing:
new_locations.append(Regions.lookup_name_to_id[location])
for location, (loc_roomid, loc_mask) in location_table_uw.items(): for location, (loc_roomid, loc_mask) in location_table_uw.items():
try: try:
if location not in ctx.locations_checked and loc_roomid == roomid and (roomdata << 4) & loc_mask != 0: if location not in ctx.unsafe_locations_checked and loc_roomid == roomid and (roomdata << 4) & loc_mask != 0:
new_check(location) new_check(location)
except Exception as e: except Exception as e:
ctx.ui_node.log_info(f"Exception: {e}") ctx.ui_node.log_info(f"Exception: {e}")
@ -1153,7 +1153,7 @@ async def track_locations(ctx : Context, roomid, roomdata):
uw_end = 0 uw_end = 0
uw_unchecked = {} uw_unchecked = {}
for location, (roomid, mask) in location_table_uw.items(): for location, (roomid, mask) in location_table_uw.items():
if location not in ctx.locations_checked: if location not in ctx.unsafe_locations_checked:
uw_unchecked[location] = (roomid, mask) uw_unchecked[location] = (roomid, mask)
uw_begin = min(uw_begin, roomid) uw_begin = min(uw_begin, roomid)
uw_end = max(uw_end, roomid + 1) uw_end = max(uw_end, roomid + 1)
@ -1170,7 +1170,7 @@ async def track_locations(ctx : Context, roomid, roomdata):
ow_end = 0 ow_end = 0
ow_unchecked = {} ow_unchecked = {}
for location, screenid in location_table_ow.items(): for location, screenid in location_table_ow.items():
if location not in ctx.locations_checked: if location not in ctx.unsafe_locations_checked:
ow_unchecked[location] = screenid ow_unchecked[location] = screenid
ow_begin = min(ow_begin, screenid) ow_begin = min(ow_begin, screenid)
ow_end = max(ow_end, screenid + 1) ow_end = max(ow_end, screenid + 1)
@ -1181,22 +1181,27 @@ async def track_locations(ctx : Context, roomid, roomdata):
if ow_data[screenid - ow_begin] & 0x40 != 0: if ow_data[screenid - ow_begin] & 0x40 != 0:
new_check(location) new_check(location)
if not all([location in ctx.locations_checked for location in location_table_npc.keys()]): if not all([location in ctx.unsafe_locations_checked for location in location_table_npc.keys()]):
npc_data = await snes_read(ctx, SAVEDATA_START + 0x410, 2) npc_data = await snes_read(ctx, SAVEDATA_START + 0x410, 2)
if npc_data is not None: if npc_data is not None:
npc_value = npc_data[0] | (npc_data[1] << 8) npc_value = npc_data[0] | (npc_data[1] << 8)
for location, mask in location_table_npc.items(): for location, mask in location_table_npc.items():
if npc_value & mask != 0 and location not in ctx.locations_checked: if npc_value & mask != 0 and location not in ctx.unsafe_locations_checked:
new_check(location) new_check(location)
if not all([location in ctx.locations_checked for location in location_table_misc.keys()]): if not all([location in ctx.unsafe_locations_checked for location in location_table_misc.keys()]):
misc_data = await snes_read(ctx, SAVEDATA_START + 0x3c6, 4) misc_data = await snes_read(ctx, SAVEDATA_START + 0x3c6, 4)
if misc_data is not None: if misc_data is not None:
for location, (offset, mask) in location_table_misc.items(): for location, (offset, mask) in location_table_misc.items():
assert(0x3c6 <= offset <= 0x3c9) assert(0x3c6 <= offset <= 0x3c9)
if misc_data[offset - 0x3c6] & mask != 0 and location not in ctx.locations_checked: if misc_data[offset - 0x3c6] & mask != 0 and location not in ctx.unsafe_locations_checked:
new_check(location) new_check(location)
for location in ctx.unsafe_locations_checked:
if location in ctx.items_missing and location not in ctx.locations_checked:
ctx.locations_checked.add(location)
new_locations.append(Regions.lookup_name_to_id[location])
await ctx.send_msgs([['LocationChecks', new_locations]]) await ctx.send_msgs([['LocationChecks', new_locations]])

View File

@ -809,10 +809,7 @@ class ClientMessageProcessor(CommonCommandProcessor):
def _cmd_missing(self) -> bool: def _cmd_missing(self) -> bool:
"""List all missing location checks from the server's perspective""" """List all missing location checks from the server's perspective"""
locations = [] locations = get_missing_checks(self.ctx, self.client)
for location_id, location_name in Regions.lookup_id_to_name.items(): # cheat console is -1, keep in mind
if location_id != -1 and location_id not in self.ctx.location_checks[self.client.team, self.client.slot]:
locations.append(location_name)
if len(locations) > 0: if len(locations) > 0:
if self.client.version < [2, 3, 0]: if self.client.version < [2, 3, 0]:
@ -941,6 +938,12 @@ class ClientMessageProcessor(CommonCommandProcessor):
self.output(response) self.output(response)
return False return False
def get_missing_checks(ctx: Context, client: Client) -> list:
locations = []
for location_id, location_name in Regions.lookup_id_to_name.items(): # cheat console is -1, keep in mind
if location_id != -1 and location_id not in ctx.location_checks[client.team, client.slot]:
locations.append(location_name)
return locations
def get_client_points(ctx: Context, client: Client) -> int: def get_client_points(ctx: Context, client: Client) -> int:
return (ctx.location_check_points * len(ctx.location_checks[client.team, client.slot]) - return (ctx.location_check_points * len(ctx.location_checks[client.team, client.slot]) -
@ -996,7 +999,7 @@ async def process_client_cmd(ctx: Context, client: Client, cmd, args):
client.tags = args.get('tags', Client.tags) client.tags = args.get('tags', Client.tags)
reply = [['Connected', [(client.team, client.slot), reply = [['Connected', [(client.team, client.slot),
[(p, ctx.get_aliased_name(t, p)) for (t, p), n in ctx.player_names.items() if [(p, ctx.get_aliased_name(t, p)) for (t, p), n in ctx.player_names.items() if
t == client.team]]]] t == client.team], get_missing_checks(ctx, client)]]]
items = get_received_items(ctx, client.team, client.slot) items = get_received_items(ctx, client.team, client.slot)
if items: if items:
reply.append(['ReceivedItems', (0, tuplize_received_items(items))]) reply.append(['ReceivedItems', (0, tuplize_received_items(items))])