I was working on a multiplayer game when I ran into a bug where the the data would be sent two times. I worked fine with a single player, but once another player joined the server, data would be sent twice. This is what the data received from the server looked like if only a single client was connected: {"player locations": [[1, 84, 100, false, ["n", "a", "m", "e"]]]}. This is the data received from the server when two clients are connected:
{"player locations": [[1, 80, 102, true, ["P", "l", "a", "y", "e", "r", "O", "n", "e"]], [2, 57, 102, false, ["P", "l", "a", "y", "e", "r", "T", "w", "o"]]]}{"player locations": [[1, 80, 102, true, ["P", "l", "a", "y", "e", "r", "O", "n", "e"]], [2, 57, 102, false, ["P", "l", "a", "y", "e", "r", "T", "w", "o"]]]} This is the data that the server sent
b'{"player locations": [[1, 80, 102, true, ["P", "l", "a", "y", "e", "r", "O", "n", "e"]], [2, 57, 102, false, ["P", "l", "a", "y", "e", "r", "T", "w", "o"]]]}' This is the server.py file's code:
IMPORTS/SETUP -------------------------------------------------------------------------------------------------------- # import socket, sys, json import threading # FUNCTIONS ------------------------------------------------------------------------------------------------------------ # def get_ip_port(path): with open(path, "r") as ipf: ipf_data = ipf.read() ipf.close() data_split = ipf_data.split(":") return [data_split[0],int(data_split[1])] print(get_ip_port("serverip.txt")) def update_clients(updatemessage): """ update_data[0][0] is the player's x pos update_data[0][1] is the player's y pos update_data[1] is the player's flip bool update_data[2] is the player's name str :param updatemessage: :return: """ # player key structure: {playerid:[[x,y],flip,name]} update_data = json.loads(updatemessage) playerid = [key for key in update_data.keys()][0] update_lst = update_data[playerid] playerid = update_lst[0] #print(update_lst) #print(playerid) print(players) if playerid == 0: return playermap[playerid][0][0] = update_lst[1] playermap[playerid][0][1] = update_lst[2] playermap[playerid][1] = update_lst[3] playermap[playerid][2] = update_lst[4] remove = [] for player_socket in players: update = {'player locations':[]} for key, value in playermap.items(): update['player locations'].append([key, value[0][0], value[0][1], value[1], value[2]]) try: print(json.dumps(update).encode()) player_socket.sendall(json.dumps(update).encode()) except Exception as e: remove.append(player_socket) print(e) continue for r in remove: players.remove(r) def client_thread(conn, player_id): while True: try: recvdata = conn.recv(bufsize) if recvdata: update_clients(recvdata) else: break except Exception as e: print(e) break playermap.pop(player_id) players.remove(conn) conn.close() # VARIABLES ------------------------------------------------------------------------------------------------------------ # MAX_PLAYER_COUNT = 15 ipport = get_ip_port("serverip.txt") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(tuple(ipport)) s.listen(MAX_PLAYER_COUNT+1) bufsize = 2048 global playermap global players players = [] playermap = {} playerstartpos = [50,50] print("Server has started, waiting for connections.") #player key structure: {playerid:[[x,y],flip,name]} # SERVER LOOP ---------------------------------------------------------------------------------------------------------- # while True: conn, addr = s.accept() print(f"Connection from {addr}") players.append(conn) playerid = len(players) playermap[playerid] = [[playerstartpos[0], playerstartpos[1]],False,""] conn.send(json.dumps({"id update": playerid}).encode()) pthread = threading.Thread(target=client_thread, args=[conn,playerid]) pthread.start() and this is the code in the client.py file that receives the data from the server:
# player key structure: {playerid:[[x,y],flip,name]} # update = {'player locations':[[value.id, value.x, value.y, value.flip, value.name]]} ins, outs, ex = select.select([n.socket], [], [], 0) for in_ in ins: data = in_.recv(2048) print(data.decode() + "\n") if data: try: socket_event = json.loads(data) except Exception as e: print(e) event_type = [key for key in socket_event.keys()][0] event_data_lst = socket_event[event_type] if event_type == 'id update': player.id = event_data_lst if event_type == 'player locations': #socket_event.pop(0) players = [] for splayer in event_data_lst: if splayer[0] != player.id: socket_player = Player((splayer[1], splayer[2]), (15,37), splayer[4], splayer[0]) socket_player.flip = splayer[3] players.append(socket_player) #else: # player.x = splayer[1] # player.y = splayer[2]