2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  argparse  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  asyncio  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  functools  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  json  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  re  
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  shlex  
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  urllib . request  
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  zlib  
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 15:45:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  ModuleUpdate  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ModuleUpdate . update ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  websockets  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  aioconsole  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  Items  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  Regions  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  MultiClient  import  ReceivedItem ,  get_item_name_from_id ,  get_location_name_from_address  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Client :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  socket ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . socket  =  socket 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . auth  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . name  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . team  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . slot  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . send_index  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Context :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  host ,  port ,  password ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . data_filename  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . save_filename  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . disable_save  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . player_names  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . rom_names  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . remote_items  =  set ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . locations  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . host  =  host 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . port  =  port 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . password  =  password 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . server  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-10 22:44:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . countdown_timer  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . clients  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . received_items  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  send_msgs ( websocket ,  msgs ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  websocket  or  not  websocket . open  or  websocket . closed : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  websocket . send ( json . dumps ( msgs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  websockets . ConnectionClosed : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pass 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  broadcast_all ( ctx  :  Context ,  msgs ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  client  in  ctx . clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  client . auth : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            asyncio . create_task ( send_msgs ( client . socket ,  msgs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  broadcast_team ( ctx  :  Context ,  team ,  msgs ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  client  in  ctx . clients : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  client . auth  and  client . team  ==  team : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            asyncio . create_task ( send_msgs ( client . socket ,  msgs ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  notify_all ( ctx  :  Context ,  text ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . info ( " Notice (all):  %s "  %  text ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    broadcast_all ( ctx ,  [ [ ' Print ' ,  text ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  notify_team ( ctx  :  Context ,  team  :  int ,  text  :  str ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . info ( " Notice (Team # %d ):  %s "  %  ( team + 1 ,  text ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    broadcast_team ( ctx ,  team ,  [ [ ' Print ' ,  text ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  notify_client ( client  :  Client ,  text  :  str ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  client . auth : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . info ( " Notice (Player  %s  in team  %d ):  %s "  %  ( client . name ,  client . team + 1 ,  text ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    asyncio . create_task ( send_msgs ( client . socket ,   [ [ ' Print ' ,  text ] ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  server ( websocket ,  path ,  ctx  :  Context ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    client  =  Client ( websocket ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . clients . append ( client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  on_client_connected ( ctx ,  client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        async  for  data  in  websocket : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  msg  in  json . loads ( data ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  len ( msg )  ==  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    cmd  =  msg 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    args  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    cmd  =  msg [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    args  =  msg [ 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                await  process_client_cmd ( ctx ,  client ,  cmd ,  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-16 18:39:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  isinstance ( e ,  websockets . WebSocketException ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            logging . exception ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  on_client_disconnected ( ctx ,  client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . clients . remove ( client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  on_client_connected ( ctx  :  Context ,  client  :  Client ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-15 03:00:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    await  send_msgs ( client . socket ,  [ [ ' RoomInfo ' ,  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' password ' :  ctx . password  is  not  None , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ' players ' :  [ ( client . team ,  client . slot ,  client . name )  for  client  in  ctx . clients  if  client . auth ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ] ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  on_client_disconnected ( ctx  :  Context ,  client  :  Client ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  client . auth : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  on_client_left ( ctx ,  client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  on_client_joined ( ctx  :  Context ,  client  :  Client ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    notify_all ( ctx ,  " %s  (Team # %d ) has joined the game "  %  ( client . name ,  client . team  +  1 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  on_client_left ( ctx  :  Context ,  client  :  Client ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    notify_all ( ctx ,  " %s  (Team # %d ) has left the game "  %  ( client . name ,  client . team  +  1 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-10 22:44:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								async  def  countdown ( ctx  :  Context ,  timer ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    notify_all ( ctx ,  f ' [Server]: Starting countdown of  { timer } s ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ctx . countdown_timer : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . countdown_timer  =  timer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . countdown_timer  =  timer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ctx . countdown_timer  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        notify_all ( ctx ,  f ' [Server]:  { ctx . countdown_timer } ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . countdown_timer  - =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  asyncio . sleep ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    notify_all ( ctx ,  f ' [Server]: GO ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  get_connected_players_string ( ctx  :  Context ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auth_clients  =  [ c  for  c  in  ctx . clients  if  c . auth ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  auth_clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ' No player connected ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auth_clients . sort ( key = lambda  c :  ( c . team ,  c . slot ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    current_team  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    text  =  ' Team #1:  ' 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    for  c  in  auth_clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  c . team  !=  current_team : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            text  + =  f ' :: Team # { c . team  +  1 } :  ' 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            current_team  =  c . team 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        text  + =  f ' { c . name }   ' 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    return  ' Connected players:  '  +  text [ : - 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_received_items ( ctx  :  Context ,  team ,  player ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ctx . received_items . setdefault ( ( team ,  player ) ,  [ ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  tuplize_received_items ( items ) :  
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  [ ( item . item ,  item . location ,  item . player )  for  item  in  items ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  send_new_items ( ctx  :  Context ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  client  in  ctx . clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  client . auth : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        items  =  get_received_items ( ctx ,  client . team ,  client . slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( items )  >  client . send_index : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            asyncio . create_task ( send_msgs ( client . socket ,  [ [ ' ReceivedItems ' ,  ( client . send_index ,  tuplize_received_items ( items ) [ client . send_index : ] ) ] ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            client . send_index  =  len ( items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  forfeit_player ( ctx  :  Context ,  team ,  slot ) :  
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    all_locations  =  [ values [ 0 ]  for  values  in  Regions . location_table . values ( )  if  type ( values [ 0 ] )  is  int ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    notify_all ( ctx ,  " %s  (Team # %d ) has forfeited "  %  ( ctx . player_names [ ( team ,  slot ) ] ,  team  +  1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    register_location_checks ( ctx ,  team ,  slot ,  all_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  register_location_checks ( ctx  :  Context ,  team ,  slot ,  locations ) :  
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    found_items  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  location  in  locations : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( location ,  slot )  in  ctx . locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            target_item ,  target_player  =  ctx . locations [ ( location ,  slot ) ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  target_player  !=  slot  or  slot  in  ctx . remote_items : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                found  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                recvd_items  =  get_received_items ( ctx ,  team ,  target_player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  recvd_item  in  recvd_items : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  recvd_item . location  ==  location  and  recvd_item . player  ==  slot : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                        found  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  not  found : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    new_item  =  ReceivedItem ( target_item ,  location ,  slot ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    recvd_items . append ( new_item ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 11:26:45 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  slot  !=  target_player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        broadcast_team ( ctx ,  team ,  [ [ ' ItemSent ' ,  ( slot ,  location ,  target_player ,  target_item ) ] ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    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 ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    found_items  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    send_new_items ( ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  found_items  and  not  ctx . disable_save : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            with  open ( ctx . save_filename ,  " wb " )  as  f : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                jsonstr  =  json . dumps ( ( list ( ctx . rom_names . items ( ) ) , 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                      [ ( k ,  [ i . __dict__  for  i  in  v ] )  for  k ,  v  in  ctx . received_items . items ( ) ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f . write ( zlib . compress ( jsonstr . encode ( " utf-8 " ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logging . exception ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  process_client_cmd ( ctx  :  Context ,  client  :  Client ,  cmd ,  args ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  type ( cmd )  is  not  str : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  send_msgs ( client . socket ,  [ [ ' InvalidCmd ' ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  cmd  ==  ' Connect ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  args  or  type ( args )  is  not  dict  or  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ' password '  not  in  args  or  type ( args [ ' password ' ] )  not  in  [ str ,  type ( None ) ]  or  \
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                ' rom '  not  in  args  or  type ( args [ ' rom ' ] )  is  not  list : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  [ [ ' InvalidArguments ' ,  ' Connect ' ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        errors  =  set ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ctx . password  is  not  None  and  args [ ' password ' ]  !=  ctx . password : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            errors . add ( ' InvalidPassword ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  tuple ( args [ ' rom ' ] )  not  in  ctx . rom_names : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            errors . add ( ' InvalidRom ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            team ,  slot  =  ctx . rom_names [ tuple ( args [ ' rom ' ] ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  any ( [ c . slot  ==  slot  and  c . team  ==  team  for  c  in  ctx . clients  if  c . auth ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                errors . add ( ' SlotAlreadyTaken ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                client . name  =  ctx . player_names [ ( team ,  slot ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                client . team  =  team 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                client . slot  =  slot 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  errors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  [ [ ' ConnectionRefused ' ,  list ( errors ) ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            client . auth  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            reply  =  [ [ ' Connected ' ,  [ ( client . team ,  client . slot ) ,  [ ( p ,  n )  for  ( t ,  p ) ,  n  in  ctx . player_names . items ( )  if  t  ==  client . team ] ] ] ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            items  =  get_received_items ( ctx ,  client . team ,  client . slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                reply . append ( [ ' ReceivedItems ' ,  ( 0 ,  tuplize_received_items ( items ) ) ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                client . send_index  =  len ( items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  reply ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  on_client_joined ( ctx ,  client ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  client . auth : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  cmd  ==  ' Sync ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        items  =  get_received_items ( ctx ,  client . team ,  client . slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            client . send_index  =  len ( items ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  [ [ ' ReceivedItems ' ,  ( 0 ,  tuplize_received_items ( items ) ) ] ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  cmd  ==  ' LocationChecks ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  type ( args )  is  not  list : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  [ [ ' InvalidArguments ' ,  ' LocationChecks ' ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        register_location_checks ( ctx ,  client . team ,  client . slot ,  args ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    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 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        logging . info ( f " { client . name }  in team  { client . team + 1 }  scouted  { ' ,  ' . join ( [ l [ 0 ]  for  l  in  locs ] ) } " ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        await  send_msgs ( client . socket ,  [ [ ' LocationInfo ' ,  [ l [ 1 : ]  for  l  in  locs ] ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  cmd  ==  ' Say ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  type ( args )  is  not  str  or  not  args . isprintable ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  send_msgs ( client . socket ,  [ [ ' InvalidArguments ' ,  ' Say ' ] ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        notify_all ( ctx ,  client . name  +  ' :  '  +  args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-10 22:44:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . startswith ( ' !players ' ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            notify_all ( ctx ,  get_connected_players_string ( ctx ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-10 22:44:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . startswith ( ' !forfeit ' ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            forfeit_player ( ctx ,  client . team ,  client . slot ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-10 22:44:07 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  args . startswith ( ' !countdown ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                timer  =  int ( args . split ( ) [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            except  ( IndexError ,  ValueError ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                timer  =  10 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            asyncio . create_task ( countdown ( ctx ,  timer ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  set_password ( ctx  :  Context ,  password ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . password  =  password 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . warning ( ' Password set to  '  +  password  if  password  is  not  None  else  ' Password disabled ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  console ( ctx  :  Context ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        input  =  await  aioconsole . ainput ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            command  =  shlex . split ( input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  command : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /exit ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ctx . server . ws_server . close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /players ' : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 14:41:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                logging . info ( get_connected_players_string ( ctx ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /password ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                set_password ( ctx ,  command [ 1 ]  if  len ( command )  >  1  else  None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /kick '  and  len ( command )  >  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                team  =  int ( command [ 2 ] )  -  1  if  len ( command )  >  2  and  command [ 2 ] . isdigit ( )  else  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  client  in  ctx . clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  client . auth  and  client . name . lower ( )  ==  command [ 1 ] . lower ( )  and  ( team  is  None  or  team  ==  client . team ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  client . socket  and  not  client . socket . closed : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            await  client . socket . close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /forfeitslot '  and  len ( command )  >  1  and  command [ 1 ] . isdigit ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  len ( command )  >  2  and  command [ 2 ] . isdigit ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    team  =  int ( command [ 1 ] )  -  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    slot  =  int ( command [ 2 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    team  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    slot  =  int ( command [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                forfeit_player ( ctx ,  team ,  slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /forfeitplayer '  and  len ( command )  >  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                team  =  int ( command [ 2 ] )  -  1  if  len ( command )  >  2  and  command [ 2 ] . isdigit ( )  else  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  client  in  ctx . clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  client . auth  and  client . name . lower ( )  ==  command [ 1 ] . lower ( )  and  ( team  is  None  or  team  ==  client . team ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  client . socket  and  not  client . socket . closed : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            forfeit_player ( ctx ,  client . team ,  client . slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /senditem '  and  len ( command )  >  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ ( player ,  item ) ]  =  re . findall ( r ' \ S* ( \ S*) (.*) ' ,  input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  item  in  Items . item_table : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    for  client  in  ctx . clients : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  client . auth  and  client . name . lower ( )  ==  player . lower ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            new_item  =  ReceivedItem ( Items . item_table [ item ] [ 3 ] ,  " cheat console " ,  client . slot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            get_received_items ( ctx ,  client . team ,  client . slot ) . append ( new_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            notify_all ( ctx ,  ' Cheat console: sending  " '  +  item  +  ' "  to  '  +  client . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    send_new_items ( ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 14:41:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    logging . warning ( " Unknown item:  "  +  item ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  command [ 0 ]  ==  ' /hint ' : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:57:38 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                for  ( team , slot ) ,  name  in  ctx . player_names . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  len ( command )  ==  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        print ( " Use /hint  {Playername}   {itemname} \n For example /hint Berserker Lamp " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    elif  name . lower ( )  ==  command [ 1 ] . lower ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        item  =  "   " . join ( command [ 2 : ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  item  in  Items . item_table : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            seeked_item_id  =  Items . item_table [ item ] [ 3 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            for  check ,  result  in  ctx . locations . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                item_id ,  receiving_player  =  result 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:57:38 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                if  receiving_player  ==  slot  and  item_id  ==  seeked_item_id : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    location_id ,  finding_player  =  check 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:57:38 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    name_finder  =  ctx . player_names [ team ,  finding_player ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 15:45:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    hint  =  f " [Hint]:  { name } ' s  { item }  can be found at  "  \
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:57:38 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                           f " { get_location_name_from_address ( location_id ) }  in  { name_finder } ' s World " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    notify_team ( ctx ,  team ,  hint ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        else : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 14:41:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            logging . warning ( " Unknown item:  "  +  item ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-15 00:34:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  command [ 0 ] [ 0 ]  !=  ' / ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                notify_all ( ctx ,  ' [Server]:  '  +  input ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        except : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            traceback . print_exc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  main ( ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser  =  argparse . ArgumentParser ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --host ' ,  default = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --port ' ,  default = 38281 ,  type = int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --password ' ,  default = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --multidata ' ,  default = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --savefile ' ,  default = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parser . add_argument ( ' --disable_save ' ,  default = False ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    parser . add_argument ( ' --loglevel ' ,  default = ' info ' ,  choices = [ ' debug ' ,  ' info ' ,  ' warning ' ,  ' error ' ,  ' critical ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    args  =  parser . parse_args ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . basicConfig ( format = ' [ %(asctime)s ]  %(message)s ' ,  level = getattr ( logging ,  args . loglevel . upper ( ) ,  logging . INFO ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    ctx  =  Context ( args . host ,  args . port ,  args . password ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . data_filename  =  args . multidata 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  ctx . data_filename : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            import  tkinter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            import  tkinter . filedialog 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            root  =  tkinter . Tk ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            root . withdraw ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ctx . data_filename  =  tkinter . filedialog . askopenfilename ( filetypes = ( ( " Multiworld data " , " *multidata " ) , ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( ctx . data_filename ,  ' rb ' )  as  f : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            jsonobj  =  json . loads ( zlib . decompress ( f . read ( ) ) . decode ( " utf-8 " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  team ,  names  in  enumerate ( jsonobj [ ' names ' ] ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                for  player ,  name  in  enumerate ( names ,  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ctx . player_names [ ( team ,  player ) ]  =  name 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:50:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            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 ' ] } 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        logging . error ( ' Failed to read multiworld data ( %s ) '  %  e ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ip  =  urllib . request . urlopen ( ' https://v4.ident.me ' ) . read ( ) . decode ( ' utf8 ' )  if  not  ctx . host  else  ctx . host 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . info ( ' Hosting game at  %s : %d  ( %s ) '  %  ( ip ,  ctx . port ,  ' No password '  if  not  ctx . password  else  ' Password:  %s '  %  ctx . password ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . disable_save  =  args . disable_save 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  ctx . disable_save : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  ctx . save_filename : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ctx . save_filename  =  ( ctx . data_filename [ : - 9 ]  if  ctx . data_filename [ - 9 : ]  ==  ' multidata '  else  ( ctx . data_filename  +  ' _ ' ) )  +  ' multisave ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            with  open ( ctx . save_filename ,  ' rb ' )  as  f : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-04 22:08:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                jsonobj  =  json . loads ( zlib . decompress ( f . read ( ) ) . decode ( " utf-8 " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-14 10:42:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                rom_names  =  jsonobj [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                received_items  =  { tuple ( k ) :  [ ReceivedItem ( * * i )  for  i  in  v ]  for  k ,  v  in  jsonobj [ 1 ] } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  not  all ( [ ctx . rom_names [ tuple ( rom ) ]  ==  ( team ,  slot )  for  rom ,  ( team ,  slot )  in  rom_names ] ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    raise  Exception ( ' Save file mismatch, will start a new game ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ctx . received_items  =  received_items 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                logging . info ( ' Loaded save file with  %d  received items for  %d  players '  %  ( sum ( [ len ( p )  for  p  in  received_items . values ( ) ] ) ,  len ( received_items ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        except  FileNotFoundError : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . error ( ' No save data found, starting a new game ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 12:21:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . info ( e ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-09 19:27:56 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ctx . server  =  websockets . serve ( functools . partial ( server , ctx = ctx ) ,  ctx . host ,  ctx . port ,  ping_timeout = None ,  ping_interval = None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    await  ctx . server 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    await  console ( ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ( )