diff options
| author | Choupom <andycootlapin@hotmail.fr> | 2011-06-27 14:23:03 +0200 |
|---|---|---|
| committer | oy <Tom_Adams@web.de> | 2011-06-27 16:45:55 +0200 |
| commit | d6f34cbaba8b411db12bb88278e6c552d32b0314 (patch) | |
| tree | 723247f9a26d78ff4bd3e7cfa2e27d2bb6295c4b /scripts | |
| parent | 99c2c53c0b5fbd61e4d71e2f4967a5771c8296f8 (diff) | |
| download | zcatch-d6f34cbaba8b411db12bb88278e6c552d32b0314.tar.gz zcatch-d6f34cbaba8b411db12bb88278e6c552d32b0314.zip | |
updated tw_api.py for 0.6 and improved it
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/tw_api.py | 311 |
1 files changed, 225 insertions, 86 deletions
diff --git a/scripts/tw_api.py b/scripts/tw_api.py index 054a4fa2..36cc5f5e 100644 --- a/scripts/tw_api.py +++ b/scripts/tw_api.py @@ -2,18 +2,57 @@ from socket import * import struct import sys +import threading +import time -def get_server_info(address, port): + + +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, type): + self.address = address + self.type = type + 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(1.5); - sock.sendto("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief", (address, port)) - data, addr = sock.recvfrom(1024) - sock.close() - + 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] @@ -24,108 +63,208 @@ def get_server_info(address, port): server_info["num_players"] = int(slots[6]) server_info["max_players"] = int(slots[7]) server_info["players"] = [] - + for i in xrange(0, server_info["num_players"]): player = {} - player["name"] = slots[8+i*2+1] - player["score"] = slots[8+i*2] - server_info["players"] += [player] - - gametypes = ["dm", "tdm", "ctf"] - try: server_info["gametype_name"] = gametypes[server_info["gametype_id"]] - except: server_info["gametype_name"] = "unknown" - + 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_count(address, port): + + +def get_server_info2(address): try: - sock = socket(AF_INET, SOCK_DGRAM) - sock.settimeout(1.5); - sock.sendto("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffcoun", (address, port)) - data, addr = sock.recvfrom(1024) - sock.close() - + 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 - return struct.unpack(">H", data)[0] + 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 xrange(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: - return -1 + sock.close() + return None -def get_servers(address): - counter = 0 - master_port = 8300 + +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 xrange(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(1.5) - sock.sendto("\x20\x00\x00\x00\x00\x00\xff\xff\xff\xffreqt", (address, master_port)) - + 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) / 6 + data = data[14:] + num_servers = len(data) / 18 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]] + 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: # timeout + except: sock.close() - return servers -def get_all_servers(): - servers = [] - for i in range(1, 16): - addr = "master%d.teeworlds.com"%i - list = get_servers(addr) - if list: - #print addr, "had", len(list), "servers" - servers += list return servers -servers = get_all_servers() -total_players = 0 -players_per_versions = {} -versions = {} -gametypes = {} -if 1: - for server in servers: - #print "checking server", server[0], server[1] - info = get_server_info(server[0], server[1]) - if info: - total_players += len(info["players"]) - if info["version"] in versions: - versions[info["version"]] += 1 - else: - versions[info["version"]] = 1 - if info["version"] in players_per_versions: - players_per_versions[info["version"]] += len(info["players"]) - else: - players_per_versions[info["version"]] = len(info["players"]) - if info["gametype"] in gametypes: - gametypes[info["gametype"]] += 1 - else: - gametypes[info["gametype"]] = 1 +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 == True: + if master_servers[0].servers: + servers += master_servers[0].servers + del master_servers[0] + time.sleep(0.001) # be nice + +servers_info = [] -print total_players - -if 0: - print total_players, "on", len(servers), 'servers' - print "versions:" - for v in versions: - print "\t",v, versions[v] +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 == True: + + 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"] - print "players per version:" - for v in players_per_versions: - print "\t",v, players_per_versions[v] + del servers_info[0] - print "gametypes:" - for v in gametypes: - print "\t",v, gametypes[v] + time.sleep(0.001) # be nice +print str(num_players) + " players and " + str(num_clients-num_players) + " spectators" |