# coding: utf-8 # pylint: skip-file from socket import socket, AF_INET, SOCK_DGRAM import sys import threading import time NUM_MASTERSERVERS = 4 MASTERSERVER_PORT = 8300 TIMEOUT = 2 SERVERTYPE_NORMAL = 0 SERVERTYPE_LEGACY = 1 PACKET_GETLIST = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreqt" PACKET_GETLIST2 = "\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreq2" PACKET_GETINFO = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief" PACKET_GETINFO2 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie2" + "\x00" PACKET_GETINFO3 = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgie3" + "\x00" class Server_Info(threading.Thread): def __init__(self, address, typ): self.address = address self.type = typ self.finished = False threading.Thread.__init__(self, target = self.run) def run(self): self.info = None if self.type == SERVERTYPE_NORMAL: self.info = get_server_info3(self.address) elif self.type == SERVERTYPE_LEGACY: self.info = get_server_info(self.address) if self.info: self.info = get_server_info2(self.address) self.finished = True def get_server_info(address): try: sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.sendto(PACKET_GETINFO, address) data, _addr = sock.recvfrom(1024) sock.close() data = data[14:] # skip header slots = data.split("\x00") server_info = {} server_info["version"] = slots[0] server_info["name"] = slots[1] server_info["map"] = slots[2] server_info["gametype"] = slots[3] server_info["flags"] = int(slots[4]) server_info["progression"] = int(slots[5]) server_info["num_players"] = int(slots[6]) server_info["max_players"] = int(slots[7]) server_info["players"] = [] for i in range(0, server_info["num_players"]): player = {} player["name"] = slots[8+i*2] player["score"] = int(slots[8+i*2+1]) server_info["players"].append(player) return server_info except: sock.close() return None def get_server_info2(address): try: sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.sendto(PACKET_GETINFO2, address) data, _addr = sock.recvfrom(1024) sock.close() data = data[14:] # skip header slots = data.split("\x00") server_info = {} server_info["token"] = slots[0] server_info["version"] = slots[1] server_info["name"] = slots[2] server_info["map"] = slots[3] server_info["gametype"] = slots[4] server_info["flags"] = int(slots[5]) server_info["progression"] = int(slots[6]) server_info["num_players"] = int(slots[7]) server_info["max_players"] = int(slots[8]) server_info["players"] = [] for i in range(0, server_info["num_players"]): player = {} player["name"] = slots[9+i*2] player["score"] = int(slots[9+i*2+1]) server_info["players"].append(player) return server_info except: sock.close() return None def get_server_info3(address): try: sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.sendto(PACKET_GETINFO3, address) data, addr = sock.recvfrom(1400) sock.close() data = data[14:] # skip header slots = data.split("\x00") server_info = {} server_info["token"] = slots[0] server_info["version"] = slots[1] server_info["name"] = slots[2] server_info["map"] = slots[3] server_info["gametype"] = slots[4] server_info["flags"] = int(slots[5]) server_info["num_players"] = int(slots[6]) server_info["max_players"] = int(slots[7]) server_info["num_clients"] = int(slots[8]) server_info["max_clients"] = int(slots[9]) server_info["players"] = [] for i in range(0, server_info["num_clients"]): player = {} player["name"] = slots[10+i*5] player["clan"] = slots[10+i*5+1] player["country"] = int(slots[10+i*5+2]) player["score"] = int(slots[10+i*5+3]) if int(slots[10+i*5+4]): player["player"] = True else: player["player"] = False server_info["players"].append(player) return server_info except: sock.close() return None class Master_Server_Info(threading.Thread): def __init__(self, address): self.address = address self.finished = False threading.Thread.__init__(self, target = self.run) def run(self): self.servers = get_list(self.address) + get_list2(self.address) self.finished = True def get_list(address): servers = [] try: sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.sendto(PACKET_GETLIST, address) while 1: data, _addr = sock.recvfrom(1024) data = data[14:] num_servers = len(data) / 6 for n in range(0, num_servers): ip = ".".join(map(str, map(ord, data[n*6:n*6+4]))) port = ord(data[n*6+5]) * 256 + ord(data[n*6+4]) servers += [[(ip, port), SERVERTYPE_LEGACY]] except: sock.close() return servers def get_list2(address): servers = [] try: sock = socket(AF_INET, SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.sendto(PACKET_GETLIST2, address) while 1: data, _addr = sock.recvfrom(1400) data = data[14:] num_servers = len(data) / 18 for n in range(0, num_servers): if data[n*18:n*18+12] == "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff": ip = ".".join(map(str, map(ord, data[n*18+12:n*18+16]))) else: ip = ":".join(map(str, map(ord, data[n*18:n*18+16]))) port = (ord(data[n*18+16])<<8) + ord(data[n*18+17]) servers += [[(ip, port), SERVERTYPE_NORMAL]] except: sock.close() return servers master_servers = [] for i in range(1, NUM_MASTERSERVERS+1): m = Master_Server_Info(("master%d.teeworlds.com"%i, MASTERSERVER_PORT)) master_servers.append(m) m.start() time.sleep(0.001) # avoid issues servers = [] while len(master_servers) != 0: if master_servers[0].finished: if master_servers[0].servers: servers += master_servers[0].servers del master_servers[0] time.sleep(0.001) # be nice servers_info = [] print(str(len(servers)) + " servers") for server in servers: s = Server_Info(server[0], server[1]) servers_info.append(s) s.start() time.sleep(0.001) # avoid issues num_players = 0 num_clients = 0 while len(servers_info) != 0: if servers_info[0].finished: if servers_info[0].info: num_players += servers_info[0].info["num_players"] if servers_info[0].type == SERVERTYPE_NORMAL: num_clients += servers_info[0].info["num_clients"] else: num_clients += servers_info[0].info["num_players"] del servers_info[0] time.sleep(0.001) # be nice print(str(num_players) + " players and " + str(num_clients-num_players) + " spectators")