mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00
Merge branch 'pull/5'
# Conflicts: # MultiClient.py # MultiServer.py # Mystery.py
This commit is contained in:
@@ -30,6 +30,7 @@ class Context:
|
||||
self.disable_save = False
|
||||
self.player_names = {}
|
||||
self.rom_names = {}
|
||||
self.remote_items = set()
|
||||
self.locations = {}
|
||||
self.host = host
|
||||
self.port = port
|
||||
@@ -58,17 +59,17 @@ def broadcast_team(ctx : Context, team, msgs):
|
||||
asyncio.create_task(send_msgs(client.socket, msgs))
|
||||
|
||||
def notify_all(ctx : Context, text):
|
||||
print("Notice (all): %s" % text)
|
||||
logging.info("Notice (all): %s" % text)
|
||||
broadcast_all(ctx, [['Print', text]])
|
||||
|
||||
def notify_team(ctx : Context, team : int, text : str):
|
||||
print("Notice (Team #%d): %s" % (team+1, text))
|
||||
logging.info("Notice (Team #%d): %s" % (team+1, text))
|
||||
broadcast_team(ctx, team, [['Print', text]])
|
||||
|
||||
def notify_client(client : Client, text : str):
|
||||
if not client.auth:
|
||||
return
|
||||
print("Notice (Player %s in team %d): %s" % (client.name, client.team+1, text))
|
||||
logging.info("Notice (Player %s in team %d): %s" % (client.name, client.team+1, text))
|
||||
asyncio.create_task(send_msgs(client.socket, [['Print', text]]))
|
||||
|
||||
async def server(websocket, path, ctx : Context):
|
||||
@@ -162,7 +163,7 @@ def register_location_checks(ctx : Context, team, slot, locations):
|
||||
for location in locations:
|
||||
if (location, slot) in ctx.locations:
|
||||
target_item, target_player = ctx.locations[(location, slot)]
|
||||
if target_player != slot:
|
||||
if target_player != slot or slot in ctx.remote_items:
|
||||
found = False
|
||||
recvd_items = get_received_items(ctx, team, target_player)
|
||||
for recvd_item in recvd_items:
|
||||
@@ -172,8 +173,9 @@ def register_location_checks(ctx : Context, team, slot, locations):
|
||||
if not found:
|
||||
new_item = ReceivedItem(target_item, location, slot)
|
||||
recvd_items.append(new_item)
|
||||
broadcast_team(ctx, team, [['ItemSent', (slot, location, target_player, target_item)]])
|
||||
print('(Team #%d) %s sent %s to %s (%s)' % (team, ctx.player_names[(team, slot)], get_item_name_from_id(target_item), ctx.player_names[(team, target_player)], get_location_name_from_address(location)))
|
||||
if slot != target_player:
|
||||
broadcast_team(ctx, team, [['ItemSent', (slot, location, target_player, target_item)]])
|
||||
logging.info('(Team #%d) %s sent %s to %s (%s)' % (team+1, ctx.player_names[(team, slot)], get_item_name_from_id(target_item), ctx.player_names[(team, target_player)], get_location_name_from_address(location)))
|
||||
found_items = True
|
||||
send_new_items(ctx)
|
||||
|
||||
@@ -232,7 +234,7 @@ async def process_client_cmd(ctx : Context, client : Client, cmd, args):
|
||||
items = get_received_items(ctx, client.team, client.slot)
|
||||
if items:
|
||||
client.send_index = len(items)
|
||||
await send_msgs(client.socket, ['ReceivedItems', (0, tuplize_received_items(items))])
|
||||
await send_msgs(client.socket, [['ReceivedItems', (0, tuplize_received_items(items))]])
|
||||
|
||||
if cmd == 'LocationChecks':
|
||||
if type(args) is not list:
|
||||
@@ -240,6 +242,28 @@ async def process_client_cmd(ctx : Context, client : Client, cmd, args):
|
||||
return
|
||||
register_location_checks(ctx, client.team, client.slot, args)
|
||||
|
||||
if cmd == 'LocationScouts':
|
||||
if type(args) is not list:
|
||||
await send_msgs(client.socket, [['InvalidArguments', 'LocationScouts']])
|
||||
return
|
||||
locs = []
|
||||
for location in args:
|
||||
if type(location) is not int or 0 >= location > len(Regions.location_table):
|
||||
await send_msgs(client.socket, [['InvalidArguments', 'LocationScouts']])
|
||||
return
|
||||
loc_name = list(Regions.location_table.keys())[location - 1]
|
||||
target_item, target_player = ctx.locations[(Regions.location_table[loc_name][0], client.slot)]
|
||||
|
||||
replacements = {'SmallKey': 0xA2, 'BigKey': 0x9D, 'Compass': 0x8D, 'Map': 0x7D}
|
||||
item_type = [i[2] for i in Items.item_table.values() if type(i[3]) is int and i[3] == target_item]
|
||||
if item_type:
|
||||
target_item = replacements.get(item_type[0], target_item)
|
||||
|
||||
locs.append([loc_name, location, target_item, target_player])
|
||||
|
||||
logging.info(f"{client.name} in team {client.team+1} scouted {', '.join([l[0] for l in locs])}")
|
||||
await send_msgs(client.socket, [['LocationInfo', [l[1:] for l in locs]]])
|
||||
|
||||
if cmd == 'Say':
|
||||
if type(args) is not str or not args.isprintable():
|
||||
await send_msgs(client.socket, [['InvalidArguments', 'Say']])
|
||||
@@ -260,7 +284,7 @@ async def process_client_cmd(ctx : Context, client : Client, cmd, args):
|
||||
|
||||
def set_password(ctx : Context, password):
|
||||
ctx.password = password
|
||||
print('Password set to ' + password if password is not None else 'Password disabled')
|
||||
logging.warning('Password set to ' + password if password is not None else 'Password disabled')
|
||||
|
||||
async def console(ctx : Context):
|
||||
while True:
|
||||
@@ -276,7 +300,7 @@ async def console(ctx : Context):
|
||||
break
|
||||
|
||||
if command[0] == '/players':
|
||||
print(get_connected_players_string(ctx))
|
||||
logging.info(get_connected_players_string(ctx))
|
||||
if command[0] == '/password':
|
||||
set_password(ctx, command[1] if len(command) > 1 else None)
|
||||
if command[0] == '/kick' and len(command) > 1:
|
||||
@@ -310,7 +334,7 @@ async def console(ctx : Context):
|
||||
notify_all(ctx, 'Cheat console: sending "' + item + '" to ' + client.name)
|
||||
send_new_items(ctx)
|
||||
else:
|
||||
print("Unknown item: " + item)
|
||||
logging.warning("Unknown item: " + item)
|
||||
if command[0] == '/hint':
|
||||
for (team,slot), name in ctx.player_names.items():
|
||||
if len(command) == 1:
|
||||
@@ -328,7 +352,7 @@ async def console(ctx : Context):
|
||||
f"{get_location_name_from_address(location_id)} in {name_finder}'s World"
|
||||
notify_team(ctx, team, hint)
|
||||
else:
|
||||
print("Unknown item: " + item)
|
||||
logging.warning("Unknown item: " + item)
|
||||
if command[0][0] != '/':
|
||||
notify_all(ctx, '[Server]: ' + input)
|
||||
except:
|
||||
@@ -343,8 +367,11 @@ async def main():
|
||||
parser.add_argument('--multidata', default=None)
|
||||
parser.add_argument('--savefile', default=None)
|
||||
parser.add_argument('--disable_save', default=False, action='store_true')
|
||||
parser.add_argument('--loglevel', default='info', choices=['debug', 'info', 'warning', 'error', 'critical'])
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.basicConfig(format='[%(asctime)s] %(message)s', level=getattr(logging, args.loglevel.upper(), logging.INFO))
|
||||
|
||||
ctx = Context(args.host, args.port, args.password)
|
||||
|
||||
ctx.data_filename = args.multidata
|
||||
@@ -359,17 +386,18 @@ async def main():
|
||||
|
||||
with open(ctx.data_filename, 'rb') as f:
|
||||
jsonobj = json.loads(zlib.decompress(f.read()).decode("utf-8"))
|
||||
for team, names in enumerate(jsonobj[0]):
|
||||
for team, names in enumerate(jsonobj['names']):
|
||||
for player, name in enumerate(names, 1):
|
||||
ctx.player_names[(team, player)] = name
|
||||
ctx.rom_names = {tuple(rom): (team, slot) for slot, team, rom in jsonobj[1]}
|
||||
ctx.locations = {tuple(k): tuple(v) for k, v in jsonobj[2]}
|
||||
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']}
|
||||
except Exception as e:
|
||||
print('Failed to read multiworld data (%s)' % e)
|
||||
logging.error('Failed to read multiworld data (%s)' % e)
|
||||
return
|
||||
|
||||
ip = urllib.request.urlopen('https://v4.ident.me').read().decode('utf8') if not ctx.host else ctx.host
|
||||
print('Hosting game at %s:%d (%s)' % (ip, ctx.port, 'No password' if not ctx.password else 'Password: %s' % ctx.password))
|
||||
logging.info('Hosting game at %s:%d (%s)' % (ip, ctx.port, 'No password' if not ctx.password else 'Password: %s' % ctx.password))
|
||||
|
||||
ctx.disable_save = args.disable_save
|
||||
if not ctx.disable_save:
|
||||
@@ -383,11 +411,11 @@ async def main():
|
||||
if not all([ctx.rom_names[tuple(rom)] == (team, slot) for rom, (team, slot) in rom_names]):
|
||||
raise Exception('Save file mismatch, will start a new game')
|
||||
ctx.received_items = received_items
|
||||
print('Loaded save file with %d received items for %d players' % (sum([len(p) for p in received_items.values()]), len(received_items)))
|
||||
logging.info('Loaded save file with %d received items for %d players' % (sum([len(p) for p in received_items.values()]), len(received_items)))
|
||||
except FileNotFoundError:
|
||||
print('No save data found, starting a new game')
|
||||
logging.error('No save data found, starting a new game')
|
||||
except Exception as e:
|
||||
print(e)
|
||||
logging.info(e)
|
||||
|
||||
ctx.server = websockets.serve(functools.partial(server,ctx=ctx), ctx.host, ctx.port, ping_timeout=None, ping_interval=None)
|
||||
await ctx.server
|
||||
@@ -397,4 +425,4 @@ if __name__ == '__main__':
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
loop.run_until_complete(asyncio.gather(*asyncio.Task.all_tasks()))
|
||||
loop.close()
|
||||
loop.close()
|
||||
|
Reference in New Issue
Block a user