def process_join_lobby(message_obj): from_conn = message_obj.from_connection # check there is space for the client in the lobby # if so register them in :) status, err_msg = database.join_lobby(from_conn.get_client_key()[0], message_obj["lobby_id"]) if status: # change scene response_message = message.Message('s') response_message.new_message(const.SERVER_NAME, const.SCENE_NAMES["Lobby"]) else: # send error status response_message = message.Message('!') response_message.new_message(const.SERVER_NAME, statusProtocols.SS_LOBBY_REQUEST, False, err_msg) pass # send the response and disconnect if we have joined from_conn.send_message(response_message) if status: from_conn.safe_close()
def send_client_list(lobby_id): cids, nnames = database.get_lobby_player_list(lobby_id) connected_clients = message.Message('C') connected_clients.new_message(const.SERVER_NAME, cids, nnames) connected_clients.to_connections = get_lobby_connections(lobby_id) connected_clients.send_message()
def damage_object(self, objects, position): for objId in objects: # find if any objects are in range. distance = helpers.distance(position, objects[objId].transform.position) if distance < const.EXPLOSION_RANGE: damage_amt = abs( int(const.EXPLOSION_DAMAGE * (1.0 - (distance / const.EXPLOSION_RANGE)))) # if the object has died remove it and notify the other clients its dead! if objects[objId].health is not None and \ not objects[objId].health.apply_damage(damage_amt): remove_obj = message.Message('#') remove_obj.new_message( const.SERVER_NAME, objects[objId].type, objects[objId].object_id, *objects[objId].transform. position, # unpack into x, y, z game_types.SOA_REMOVE) remove_obj.to_connections = self.socket_handler.get_connections( ) remove_obj.send_message() del self.objects[objId]
def explosion(self, message_obj): position = (message_obj["x"], message_obj["y"], message_obj["z"]) connections = self.socket_handler.get_connections() damage = message.Message('D') damage.to_connections = connections for conn in connections: distance = helpers.distance(position, conn.transform.position) if distance < const.EXPLOSION_RANGE: # send damage message to all clients damage_amt = abs( int(const.EXPLOSION_DAMAGE * (1.0 - (distance / const.EXPLOSION_RANGE)))) dead = not conn.health.apply_damage(damage_amt) health = conn.health.health damage.new_message(const.SERVER_NAME, conn.player_id, health, dead) damage.send_message() DEBUG.LOGS.print("Damage: ", damage_amt, "health: ", conn.health) # work out the other objects some where else :) remove_server_object = threading.Thread(target=self.damage_object, args=(self.objects, position)) remove_server_object.start() self.analytics.add_data(message_obj)
def process_remove_connection(conn): global close_game # check there is enough players still if not we'll have to end the game :( # When the player is disconnected the selector removes them from the database. player_count = database.get_lobby_player_count(lobby_id) if player_count < active_game_model.min_players: # disconect all others status = message.Message('!') # sent the from connection to the conn disconnecting so we can ignore it when we send the message status.from_connection = conn status.to_connections = socket_handler.get_connections() status.new_message(const.SERVER_NAME, status_protocol.SS_GAME_ENOUGH_PLAYERS, False, "Not enough Players To continue.") status.send_message(True) # clear the game from the database. database.clear_game_host(game_host_id) # disconnect the remaining players from the server. connections = socket_handler.get_connections() for c in connections: if c == conn: continue DEBUG.LOGS.print(c.client_nickname, "::", c._client_db_id) c.safe_close() close_game = True
def process_client_identity( message_obj ): from_conn = message_obj.from_connection nickname = message_obj["nickname"] reg_key = message_obj["reg_key"].strip() # strip any white space client_id = -1 # if the client returns a reg_key they may already exist. if len(reg_key) > 0: # find the users in the db by there reg key user = database.select_client(reg_key) if user is None: # not found reg_key = "" else: client_id = user[0] if nickname != user[1]: database.update_client_nickname(reg_key, user[1]) # if the reg key is empty assign a new one. if len(reg_key) == 0: # assign new reg key and nickname client_id, reg_key = database.add_new_client( nickname ) status_message = message.Message( 'I' ) status_message.new_message(const.SERVER_NAME, client_id, reg_key, True) message_obj.from_connection.send_message(status_message) # Disconnect the client once all message have been sent. from_conn.safe_close() DEBUG.LOGS.print("Done")
def request_client_identity( connection ): nickname = database.get_random_name() identity_request = message.Message( 'i' ) identity_request.new_message( const.SERVER_NAME, "", nickname, "" ) connection.send_message( identity_request )
def send_lobby_info(lobby_id): level_name, min_players, max_players = database.get_lobby_info(lobby_id) # set/unset the game start time as required if lobbies_start_times[lobby_id] < 0 and get_clients_in_lobby( lobby_id) >= min_players: # queue the game now theres enough players lobbies_start_times[lobby_id] = time.time() + GAME_START_TIME queue_lobbie(lobby_id, False) elif lobbies_start_times[lobby_id] > 0 and get_clients_in_lobby( lobby_id) < min_players: # dequeue the game, now we've lost some players lobbies_start_times[lobby_id] = -1 queue_lobbie(lobby_id, True) elif lobbies_start_times[ lobby_id] > 0: # add a little more time if a new player connects. lobbies_start_times[lobby_id] += NEW_PLAYER_DELAY lobby_info = message.Message('O') lobby_info.new_message(const.SERVER_NAME, level_name, min_players, max_players, lobbies_start_times[lobby_id] - time.time()) lobby_info.to_connections = get_lobby_connections(lobby_id) lobby_info.send_message()
def send_win_message(self, win_player_id): win_message = message.Message('A') win_message.new_message(const.SERVER_NAME, win_player_id, game_types.GA_END_GAME) win_message.to_connections = self.socket_handler.get_connections() win_message.send_message() DEBUG.LOGS.print("Win Sent")
def get_message(self): x, y, z = self.transform.position msg = message.Message('#') msg.new_message(const.SERVER_NAME, self.type, self.object_id, x, y, z) return msg
def get_game_loop_message(self, game_loop_id, message_player_id): action, time = self.game_loop[game_loop_id] msg = message.Message('>') msg.new_message(const.SERVER_NAME, message_player_id, action, time) msg.to_connections = self.socket_handler.get_connections() return msg, time
def process_client_status_scene_loaded(message_obj): if message_obj[ "ok"]: # TODO: if the user is not ok, remove them from the game? if not message_obj.from_connection.ready: message_obj.from_connection.ready = True active_game_model.players_ready_count += 1 # check all the players have arrived and readied # if so send the player info. expecting_player_count = database.get_lobby_player_count(lobby_id) DEBUG.LOGS.print("Client Joined successfully! - ", message_obj.from_connection.client_nickname) if active_game_model.players_ready_count == expecting_player_count and not active_game_model.players_setup: # send out the player details to the clients available_player_ids = [ x for x in range(expecting_player_count) ] # list of player ids to assign each player at random without dups client_ids = [] nicknames = [] player_ids = [] connections = socket_handler.connections for sock in connections: cid, nn, pid = socket_handler.get_connection( sock).get_player_info() try: pid = random.choice(available_player_ids) available_player_ids.remove(pid) # assign each of the players a relic area from ActiveGame connections[sock].relic_area = active_game_model.relic_areas[ pid] except Exception as e: DEBUG.LOGS.print("No more random ids to choose for.", message_type=DEBUG.LOGS.MSG_TYPE_FATAL) client_ids.append(cid) nicknames.append(nn) player_ids.append(pid) connections[sock].player_id = pid active_game_model.players_setup = True game_info_msg = message.Message("G") game_info_msg.new_message(const.SERVER_NAME, client_ids, nicknames, player_ids) game_info_msg.to_connections = socket_handler.get_connections() game_info_msg.send_message()
def process_client_identity(message_obj): DEBUG.LOGS.print("Recivedd id", message_obj["client_id"], message_obj["reg_key"]) from_conn = message_obj.from_connection # add the clients data to the connection from_conn.set_client_key(message_obj["client_id"], message_obj["reg_key"]) # find the user in the database and make sure they have arrived at the correct location client_info = database.select_client(message_obj["reg_key"]) client_nickname = client_info[1] client_lobby_id = client_info[2] # find if the lobby exist on the server # if not double check that the client has arrive at the correct location # and create a new lobby. if client_lobby_id in lobbies: lobbies[client_lobby_id][from_conn.socket] = from_conn else: host = database.get_lobby_host_from_lobby_id(client_lobby_id) if host == config.get("internal_host"): lobbies[client_lobby_id] = {from_conn.socket: from_conn} lobbies_start_times[client_lobby_id] = -1 else: # it appears the clients has arrived at the wrong location. DEBUG.LOGS.print( "Client has arrived at the wrong lobby host. expected:", host, "actual", config.get("internal_host"), "Disconnecting...", message_type=DEBUG.LOGS.MSG_TYPE_FATAL) from_conn.safe_close() return # update the connection with the db data from_conn.lobby_id = client_lobby_id from_conn.client_nickname = client_nickname # send all the clients an updated list of connected clients send_client_list(client_lobby_id) # let everyone know you have joined msg = message.Message('m') msg.new_message(client_nickname, [], "Has Joined the Server :D Yay! ") msg.to_connections = get_lobby_connections(client_lobby_id) msg.send_message() # send start status send_lobby_info(client_lobby_id)
def intersect_data(self, id_byte, json_bytes): """ :param id_byte: the identity char byte :param json_bytes: json bytes :return: """ identity = chr(id_byte) if identity == 'I': msg = message.Message(identity) msg.set_from_json(constants.SERVER_NAME, json_bytes.decode()) self.set_client_key(msg["client_id"], msg["reg_key"]) DEBUG.LOGS.print("Client Idenity Set. id", msg["client_id"], "reg key", msg["reg_key"])
def send_client_data_to_server(self, pass_sock): """Send the clients data to the server we have just connected to""" identity_msg = message.Message("i") identity_msg.new_message(constants.SERVER_NAME, self.get_client_key()[0], "", self.get_client_key()[1]) msg = identity_msg.get_json() len_data = len(msg).to_bytes(self.MESSAGE_LEN_PACKET_SIZE, self.BYTE_ORDER) chr_data = ord('i').to_bytes(self.MESSAGE_TYPE_PACKET_SIZE, self.BYTE_ORDER) DEBUG.LOGS.print("send identity to sever", msg) return self.send_data(pass_sock, len_data + chr_data + msg.encode(), "id sender")
def clean_lobby(connection): lobby_id = connection.lobby_id client_nickname = connection.client_nickname # remove the client from the lobby if lobby_id in lobbies and connection.socket in lobbies[lobby_id]: del lobbies[lobby_id][connection.socket] # notify all the others that a client has left. msg = message.Message('m') msg.new_message(client_nickname, [], "Has Left the Server :( ") msg.to_connections = get_lobby_connections(lobby_id) msg.send_message() send_client_list(lobby_id) send_lobby_info(lobby_id)
def process_client_identity(message_obj): DEBUG.LOGS.print("Recivedd id", message_obj["client_id"], message_obj["reg_key"]) from_conn = message_obj.from_connection # TODO: have a look at makeing this bit common its the same in lobby # add the clients data to the connection from_conn.set_client_key(message_obj["client_id"], message_obj["reg_key"]) # find the user in the database and make sure they have arrived at the correct location client_info = database.select_client(message_obj["reg_key"]) client_nickname = client_info[1] client_lobby_id = client_info[2] host = database.get_client_current_game_host(message_obj["reg_key"]) # check that the client is on the correct host if host != config.get("internal_host"): DEBUG.LOGS.print( "Client has arrived at the wrong game host. expected:", config.get("internal_host"), "actual", host, "Disconnecting...", message_type=DEBUG.LOGS.MSG_TYPE_FATAL) from_conn.safe_close() # update the connection with the db data from_conn.lobby_id = client_lobby_id from_conn.client_nickname = client_nickname # notify other clients that they have joined the game server msg = message.Message('m') msg.new_message(client_nickname, [], "Has Joined the Server :D Yay! ") msg.to_connections = socket_handler.get_connections( ) # send to all clients msg.send_message()
def process_connection(conn): # process any messages from the client while conn.receive_message_pending(): conn.receive_message().run_action() if not conn.get_client_key()[1].strip(): DEBUG.LOGS.print("Unable to process client, not set up", conn.get_client_key(), message_type=DEBUG.LOGS.MSG_TYPE_WARNING) #conn.safe_close() return if time.time() > conn.next_update_time: # send the client a list of lobbies available to join current_lobby_count = database.available_lobby_count() if current_lobby_count < MIN_LOBBY_COUNT: database.add_new_lobby() lobbies, lobb_curr_players = database.select_all_available_lobbies() lobb_names = [] lobb_id = [] lobb_max_clients = [] # organize the lobby data for lobb in lobbies: lobb_id.append(lobb[0]) lobb_names.append(lobb[2]) lobb_max_clients.append(lobb[4]) conn.next_update_time = time.time() + LOBBY_UPDATE_CLIENT_INTERVALS lobby_message = message.Message("l") lobby_message.new_message(const.SERVER_NAME, lobb_names, lobb_id, lobb_curr_players, lobb_max_clients) conn.send_message(lobby_message)
def send_scene_change_message(send_message, conn, scene_name): if send_message: scene_message = message.Message('s') scene_message.new_message(const.SERVER_NAME, scene_name) conn.send_message(scene_message)
def receive_thread(self, socket): while self.valid(): # receive messages in three parts # Protocol layout. # message len (2 bytes) identity (1 byte) json message ( message len bytes) msg_len = 0 start_receive = 0 receive_id = 0 convert = 0 receive_msg = 0 print_m = 0 decode = 0 try: msg_len_data = socket.recv(self.MESSAGE_LEN_PACKET_SIZE) start_receive = time.time_ns() # check there is data. if the connection was lost we will receive 0 bytes if len(msg_len_data) == 0: self.valid(False) break msg_identity_data = socket.recv(self.MESSAGE_TYPE_PACKET_SIZE) receive_id = time.time_ns() except Exception as e: DEBUG.LOGS.print("Could not receive data", e, message_type=DEBUG.LOGS.MSG_TYPE_ERROR) self.valid(False) return # convert our bytes to int and char msg_len = int.from_bytes(msg_len_data, self.BYTE_ORDER) msg_identity = chr( int.from_bytes(msg_identity_data, self.BYTE_ORDER)) convert = time.time_ns() DEBUG.LOGS.print("Received message len:", msg_len, "Type:", msg_identity) print_m = time.time_ns() # receive the json message of msg_type with length msg_length try: json_str = self.socket.recv(msg_len) receive_msg = time.time_ns() json_str = json_str.decode("utf-8") decode = time.time_ns() except Exception as e: DEBUG.LOGS.print("Could not receive data", e, message_type=DEBUG.LOGS.MSG_TYPE_ERROR) self.valid(False) break DEBUG.LOGS.print("message ", json_str) message_obj = message.Message(msg_identity, self) message_obj.times["receive time"] = [start_receive, time.time_ns()] message_obj.set_from_json("Client", json_str) message_obj.times["time till run"] = [time.time_ns(), 0] if (message_obj.times["receive time"][1] - message_obj.times["receive time"][0]) / 1000000.0 > 5: DEBUG.LOGS.print( "\nmessage length", msg_len, "\nreceive id", (receive_id - start_receive) / 1000000.0, "\nconvert", (convert - receive_id) / 1000000.0, "\ndebug print", (print_m - convert) / 1000000.0, "\nreceive body", (receive_msg - print_m) / 1000000.0, "\ndecode body", (decode - receive_msg) / 1000000.0, message_type=DEBUG.LOGS.MSG_TYPE_TIMES) message_obj.run_action()
def relic_in_area(self, relic): # make sure that it is a relic if not isinstance(relic, serverObj.Relic): DEBUG.LOGS.print("Item is not a relic", relic) return connections = self.socket_handler.get_connections() # we only need to check the areas that have an active player. for conn in connections: area = conn.relic_area out_area = None # the area that the relic has came out of if area.bounds.contains(relic.transform): if relic.area == area: DEBUG.LOGS.print("RELIC No Change!!!!!!!!!!!!!!!!!") return # no change else: DEBUG.LOGS.print("RELIC Change!!!!!!!!!!!!!!!!!") if relic.area is not None: out_area = relic.area relic.area.remove_relic(relic) area.add_relic(relic) relic.area = area # update the client that gained a relic relic_count = message.Message('+') relic_count.new_message( const.SERVER_NAME, area. object_id, # for relic_areas the server object id match the player id area.relic_count()) conn.send_message(relic_count) # update the client who lost a relic if out_area is not None: out_conn = self.get_client_by_player_id( out_area.object_id) if out_conn is None: return relic_count = message.Message('+') relic_count.new_message( const.SERVER_NAME, out_area. object_id, # for relic_areas the server object id match the player id out_area.relic_count()) out_conn.send_message(relic_count) return out_area = None if relic.area is not None: relic.area.remove_relic(relic) out_area = relic.area if out_area is not None: out_conn = self.get_client_by_player_id(out_area.object_id) if out_conn is None: return relic_count = message.Message('+') relic_count.new_message( const.SERVER_NAME, out_area. object_id, # for relic_areas the server object id match the player id out_area.relic_count()) out_conn.send_message(relic_count) return