def wait_for_events(): if len(_client._events_stack) > 0: return # as we already have events to handle, no need to wait for more try: while True: sent = None try: sent = _client.socket.recv(_client._buffer_size).decode("utf-8") except socket.timeout: pass # timed out so keyboard/system interupts can be handled, hence the while true loop above except socket.error as e: handle_error(ErrorCode.cannot_read_socket, e, "Error reading socket while waiting for events") if not sent: continue elif _client._print_io: print("FROM SERVER <--", sent) split = (_client._received_buffer + sent).split(EOT_CHAR) _client._received_buffer = split.pop() # the last item will either be "" if the last char was an EOT_CHAR, or a partial data we need to buffer anyways for json_str in reversed(split): try: parsed = json.loads(json_str) except ValueError as e: handle_error(ErrorCode.malformed_json, e, "Could not parse json '" + json_str + "'") _client._events_stack.append(parsed) if len(_client._events_stack) > 0: return except (KeyboardInterrupt, SystemExit): disconnect()
def connect(hostname='localhost', port=3000, print_io=False): _client.hostname = hostname _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print( color.text('cyan') + 'Connecting to:', _client.hostname + ':' + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Silly Windows _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # so the blocking on recv doesn't hang forever and other system # interrupts (e.g. keyboard) can be handled _client.socket.settimeout(_client._timeout_time) _client.socket.connect((_client.hostname, _client.port)) except socket.error as e: error_code.handle_error( error_code.COULD_NOT_CONNECT, e, 'Could not connect to {}:{}'.format(_client.hostname, _client.port))
def connect(server='localhost', port=3000, print_io=False): _client.server = server _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print( color.text("cyan") + "Connecting to:", _client.server + ":" + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # stupid Windows _client.socket.settimeout( _client._timeout_time ) # so the blocking on recv doesn't hang forever and other system interupts (e.g. keyboard) can be handled _client.socket.connect((_client.server, _client.port)) except socket.error as e: error_code.handle_error( error_code.COULD_NOT_CONNECT, e, "Could not connect to " + _client.server + ":" + str(_client.port))
def _auto_handle_order(data): try: returned = _client.ai._do_order(data["name"], data["args"]) except: print("esc info", type(sys.exc_info())) handle_error(ErrorCode.ai_errored, sys.exc_info(), "AI errored executing order '" + data["name"] + "'.") send("finished", {"orderIndex": data["index"], "returned": returned})
def _auto_handle(event, data=None): g = globals() # the current module, e.g. the Client module that acts as a singleton auto_handle_function = g["_auto_handle_" + event] if auto_handle_function: return auto_handle_function(data) else: handle_error(ErrorCode.unknown_event_from_server, message=("Could not auto handle event '" + event + "'."))
def _auto_handle_delta(data): try: _client.manager.apply_delta_state(data) except: handle_error(ErrorCode.delta_merge_failure, sys.exc_info(), "Error merging delta") if _client.ai.player: # then the AI is ready for updates _client.ai.game_updated()
def _auto_handle_delta(data): try: _client.manager.apply_delta_state(data) except: error_code.handle_error(error_code.DELTA_MERGE_FAILURE, sys.exc_info(), "Error merging delta") if _client.ai.player: # then the AI is ready for updates _client.ai.game_updated()
def _auto_handle(event, data=None): g = globals() # the current module, e.g. the Client module that acts as a singleton auto_handle_function = g["_auto_handle_" + event] if auto_handle_function: return auto_handle_function(data) else: error_code.handle_error(error_code.UNKNOWN_EVENT_FROM_SERVER, message=("Could not auto handle event '" + event + "'."))
def _do_order(self, order, arguments): callback = getattr(self, camel_case_converter(order)) if callback != None: try: return callback(*arguments) except: handle_error(ErrorCode.ai_errored, sys.exc_info()[0], "AI caused exception while trying to execute order '" + order + "'.") else: handle_error(ErrorCode.reflection_failed, message="AI has no function '" + order + "' to respond with")
def _auto_handle_order(data): try: returned = _client.ai._do_order(data['name'], data['args']) except: print("esc info", type(sys.exc_info())) error_code.handle_error( error_code.AI_ERRORED, sys.exc_info(), "AI errored executing order '" + data['name'] + "'.") send("finished", {'orderIndex': data['index'], 'returned': returned})
def _do_order(self, order, arguments): callback = getattr(self, camel_case_converter(order)) if callback != None: try: return callback(*arguments) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "AI caused exception while trying to execute order '{}'.".format(order)) else: error_code.handle_error(error_code.REFLECTION_FAILED, message="AI has no function '' to respond with.".format(order))
def _auto_handle_order(data): args = deserialize(data['args'], _client.game) try: returned = _client.ai._do_order(data['name'], args) except: print('esc info', type(sys.exc_info())) error_code.handle_error( error_code.AI_ERRORED, sys.exc_info(), 'AI errored executing order "{}"'.format(data.name)) send("finished", {'orderIndex': data['index'], 'returned': returned})
def _auto_handle(event, data=None): g = globals( ) # the current module, e.g. the Client module that acts as a singleton auto_handle_function = g["_auto_handle_" + event] if auto_handle_function: return auto_handle_function(data) else: error_code.handle_error(error_code.UNKNOWN_EVENT_FROM_SERVER, message=("Could not auto handle event '" + event + "'."))
def _auto_handle_order(data): try: returned = _client.ai._do_order(data['name'], data['args']) except: print("esc info", type(sys.exc_info())) error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored executing order '" + data['name'] + "'.") send("finished", { 'orderIndex': data['index'], 'returned': returned })
def _auto_handle(event, data=None): # the current module, e.g. the Client module that acts as a singleton g = globals() auto_handle_function = g['_auto_handle_' + event] if auto_handle_function: return auto_handle_function(data) else: error_code.handle_error( error_code.UNKNOWN_EVENT_FROM_SERVER, message=('Could not auto handle event "{}".'.format(event)))
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won if _client.ai.player.won else _client.ai.player.reason_lost print("Game is over.", "I Won!" if won else "I Lost :(", "because: " + reason) try: _client.ai.end(won, reason) except: handle_error(ErrorCode.ai_errored, sys.exc_info(), "AI errored during end.") disconnect() os._exit(0)
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split[1])) or args.port joueur.client.connect(args.server, args.port, args.print_io) joueur.client.send("alias", args.game) game_name = joueur.client.wait_for_event("named") module_str = "games." + camel_case_converter(game_name) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error(error_code.GAME_NOT_FOUND, None, "Could not find the module for game '{}'.".format(game_name)) try: module = importlib.import_module(module_str) # should load Game and AI to load based on the game selected in args except ImportError as e: error_code.handle_error(error_code.REFLECTION_FAILED, e, "Could not import game module: '{}'.".format(module_str)) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "Could not initialize AI class. Probably a syntax error in your AI.") manager = GameManager(game) joueur.client.setup(game, ai, manager) joueur.client.send("play", { 'gameName': game_name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") print(color.text("cyan") + "In lobby for game '" + lobby_data['gameName'] + "' in session '" + lobby_data['gameSession'] + "'." + color.reset()) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "AI errored during game initialization") joueur.client.play()
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won if _client.ai.player.won else _client.ai.player.reason_lost print(color.text("green") + "Game is over.", "I Won!" if won else "I Lost :(", "because: " + reason + color.reset()) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored during end.") if 'message' in data: print(color.text("cyan") + data['message'] + color.reset()) disconnect() os._exit(0)
def wait_for_events(): if len(_client._events_stack) > 0: return # as we already have events to handle, no need to wait for more try: while True: sent = None try: sent = _client.socket.recv(_client._buffer_size) \ .decode('utf-8') except socket.timeout: pass # timed out so keyboard/system interrupts can be handled, # hence the while true loop above except socket.error as e: error_code.handle_error( error_code.CANNOT_READ_SOCKET, e, 'Error reading socket while waiting for events') if not sent: continue elif _client._print_io: print( color.text('magenta') + 'FROM SERVER <-- ' + str(sent) + color.reset()) split = (_client._received_buffer + sent).split(EOT_CHAR) # the last item will either be "" if the last char was an EOT_CHAR, # or a partial data we need to buffer anyways _client._received_buffer = split.pop() for json_str in reversed(split): try: parsed = json.loads(json_str) except ValueError as e: error_code.handle_error( error_code.MALFORMED_JSON, e, 'Could not parse json ""'.format(json_str)) _client._events_stack.append(parsed) if len(_client._events_stack) > 0: return except (KeyboardInterrupt, SystemExit): disconnect()
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split[1])) or args.port module_str = "games." + camel_case_converter(args.game) try: module = importlib.import_module(module_str) # should load Game and AI to load based on the game selected in args except ImportError as e: handle_error(ErrorCode.game_not_found, e, "Could not find game module: '" + module_str + "'") game = module.Game() ai = module.AI(game) manager = GameManager(game) joueur.client.setup(game, ai, manager, args.server, int(args.port), print_io=args.print_io) joueur.client.send("play", { 'gameName': game.name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") print("In Lobby for game '" + lobby_data['gameName'] + "' in session '" + lobby_data['gameSession'] + "'") manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print("Game starting") ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: handle_error(ErrorCode.ai_errored, sys.exc_info()[0], "AI errored during game initialization") joueur.client.play()
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won if _client.ai.player.won else _client.ai.player.reason_lost print( color.text("green") + "Game is over.", "I Won!" if won else "I Lost :(", "because: " + reason + color.reset()) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored during end.") if 'message' in data: print(color.text("cyan") + data['message'] + color.reset()) disconnect() os._exit(0)
def connect(server='localhost', port=3000, print_io=False): _client.server = server _client.port = int(port) _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print(color.text("cyan") + "Connecting to:", _client.server + ":" + str(_client.port) + color.reset()) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # stupid Windows _client.socket.settimeout(_client._timeout_time) # so the blocking on recv doesn't hang forever and other system interupts (e.g. keyboard) can be handled _client.socket.connect((_client.server, _client.port)) except socket.error as e: error_code.handle_error(error_code.COULD_NOT_CONNECT, e, "Could not connect to " + _client.server + ":" + str(_client.port))
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split[1])) or args.port module_str = "games." + camel_case_converter(args.game) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error(error_code.GAME_NOT_FOUND, None, "Could not find the module for game '{}'.".format(args.game)) try: module = importlib.import_module(module_str) # should load Game and AI to load based on the game selected in args except ImportError as e: error_code.handle_error(error_code.REFLECTION_FAILED, e, "Could not import game module: '{}'.".format(module_str)) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "Could not initialize AI class. Probably a syntax error in your AI.") manager = GameManager(game) joueur.client.setup(game, ai, manager, args.server, int(args.port), print_io=args.print_io) joueur.client.send("play", { 'gameName': game.name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") print(color.text("cyan") + "In lobby for game '" + lobby_data['gameName'] + "' in session '" + lobby_data['gameSession'] + "'." + color.reset()) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info()[0], "AI errored during game initialization") joueur.client.play()
def _auto_handle_over(data): won = _client.ai.player.won reason = _client.ai.player.reason_won \ if _client.ai.player.won \ else _client.ai.player.reason_lost print('{}Game is Over. {} because {}{}'.format( color.text('green'), 'I Won!' if won else 'I Lost :(', reason, color.reset())) try: _client.ai.end(won, reason) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), 'AI errored during end.') if 'message' in data: message = data['message'].replace('__HOSTNAME__', _client.hostname) print(color.text('cyan') + message + color.reset()) disconnect() os._exit(0)
def setup(game, ai, manager, server='localhost', port=3000, print_io=False): _client.game = game _client.ai = ai _client.server = server _client.port = port _client.manager = manager _client._print_io = print_io _client._received_buffer = "" _client._events_stack = [] _client._buffer_size = 1024 _client._timeout_time = 1.0 print("connecting to:", _client.server + ":" + str(_client.port)) try: _client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _client.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # stupid Windows _client.socket.settimeout(_client._timeout_time) # so the blocking on recv doesn't hang forever and other system interupts (e.g. keyboard) can be handled _client.socket.connect((_client.server, _client.port)) except socket.error as e: handle_error(ErrorCode.could_not_connect, e, "Could not connect to " + _client.server + ":" + str(_client.port))
def _auto_handle_invalid(data): try: _client.ai.invalid(data['message'], data['data'] if 'data' in data else None) except: handle_error(ErrorCode.ai_errored, sys.exc_info(), "AI errored while handling invalid data.")
def _auto_handle_fatal(data): error_code.handle_error(error_code.FATAL_EVENT, message="Got a fatal event from the server: " + data['message'])
def _auto_handle_invalid(data): try: _client.ai.invalid(data['message']) except: error_code.handle_error(error_code.AI_ERRORED, sys.exc_info(), "AI errored while handling invalid data.")
def _auto_handle_fatal(data): handle_error(ErrorCode.fatal_event, message="Got a fatal event from the server: " + data['message'])
def run(args): split_server = args.server.split(":") args.server = split_server[0] args.port = int((len(split_server) == 2 and split_server[1])) or args.port joueur.client.connect(args.server, args.port, args.print_io) joueur.client.send("alias", args.game) game_name = joueur.client.wait_for_event("named") module_str = "games." + camel_case_converter(game_name) spec = importlib.util.find_spec(module_str) if spec is None: error_code.handle_error( error_code.GAME_NOT_FOUND, None, 'Could not find the module for game "{}".'.format(game_name) ) try: # should load Game and AI to load based on the game selected in args module = importlib.import_module(module_str) except ImportError as e: error_code.handle_error( error_code.REFLECTION_FAILED, e, 'Could not import game module: "{}".'.format(module_str) ) game = module.Game() try: ai = module.AI(game) except: error_code.handle_error( error_code.AI_ERRORED, sys.exc_info()[0], 'Could not initialize the AI class. ' + 'Probably a syntax error in your AI.' ) manager = GameManager(game) joueur.client.setup(game, ai, manager) ai.set_settings(args.ai_settings) joueur.client.send("play", { 'gameName': game_name, 'password': args.password, 'requestedSession': args.session, 'clientType': "Python", 'playerName': args.name or ai.get_name() or "Python Player", 'playerIndex': args.index, 'gameSettings': args.game_settings }) lobby_data = joueur.client.wait_for_event("lobbied") if lobby_data['gameVersion'] != module.game_version: print("""{}WARNING: Game versions do not match. -> Your local game version is: {} -> Game Server's game version is: {} Version mismatch means that unexpected crashes may happen due to differing game structures!{}""".format( color.text('yellow'), str(module.game_version)[:8], str(lobby_data['gameVersion'])[:8], color.reset() ) ) print('{}In Lobby for game "{}" in session "{}".{}'.format( color.text("cyan"), lobby_data['gameName'], lobby_data['gameSession'], color.reset() ) ) manager.set_constants(lobby_data['constants']) start_data = joueur.client.wait_for_event("start") print(color.text("green") + "Game is starting." + color.reset()) ai.set_player(game.get_game_object(start_data['playerID'])) try: ai.start() ai.game_updated() except: error_code.handle_error( error_code.AI_ERRORED, sys.exc_info()[0], 'AI errored during game initialization' ) joueur.client.play()