#!/usr/bin/python3 import socket import time import sys import argparse from pprint import pprint DEBUG = False def decode_array(content): length = decode_int() l = [] for _ in range(length): l.append(content()) return l def decode_str(): global pointer l = decode_int() data = info[pointer:pointer+l].decode("utf8") pointer += l if DEBUG: print(f"read string {data} ({l})") return data def decode_int(): global pointer i = int(info[pointer]) if DEBUG: print(f"read int {i}") pointer += 1 return i def decode_version(): version = (decode_int(), decode_int(), decode_int()) return version def skip(amount): global pointer b = info[pointer:pointer+amount] if DEBUG: print(f"skipped {amount} bytes: {b} ({b.hex()})") pointer += amount def version_to_string(version): return f"{version[0]}.{version[1]}.{version[2]}" def query_server(host, port=34197): global info s = socket.socket(type=socket.SOCK_DGRAM) s.sendto(bytes.fromhex("30"), (host, port)) info = s.recvfrom(512)[0] def decode_packet(): global pointer s = {} pointer = 0 skip(13) s["server_name"] = decode_str() s["version"] = decode_version() skip(2) s["server_description"] = decode_str() skip(8) s["bind_addr"] = decode_str() skip(3) s["mods"] = decode_array(lambda: (decode_str(), decode_version())) skip(4) s["tags"] = decode_array(decode_str) s["players"] = decode_array(decode_str) return s if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("host") parser.add_argument("--port", "-p", type=int, default=34197) args = parser.parse_args() try: query_server(args.host, args.port) except Exception as e: print(f"CRITICAL:{e}") exit(2) s = decode_packet() print(f"OK: {s['server_name']}: Version {version_to_string(s['version'])}, {len(s['players'])} Players|num_players={len(s['players'])}")