def __init__(self, agar_client): self.agar_client = agar_client self.player = Player() self.dispatcher = Dispatcher(packet_s2c, self) self.player_list = {} self.team_world = World() self.team_cids = set() self.session = None self.force_player_update = False config = configparser.ConfigParser({'address': 'localhost', 'port': '5000', 'password': '', 'update_rate': '0.1'}) config.read('tagar_client.cfg') self.update_rate = config.getfloat('Settings', 'update_rate') self.scheduler = sched.scheduler(time, sleep) self.scheduler.enter(self.update_rate, 1, self.recv_update) self.scheduler.enter(self.update_rate, 1, self.send_update) thread = threading.Thread(target=self.scheduler.run) thread.setDaemon(True) thread.start() address = config.get('Server', 'address') port = config.getint('Server', 'port') password = config.get('Server', 'password') self.connect(address, port, password)
def __init__(self, session=None): self.session = session self.sid = str(session.sid) if session is not None else "" self.dispatcher = Dispatcher(packet_c2s, self) self.nick = str() self.position_x = 0.0 self.position_y = 0.0 self.total_mass = 0.0 self.own_ids = set() self.is_alive = False self.party_token = str() self.is_updated = False self.world = World() self.last_update_time = monotonic()
class TagarClient: def __init__(self, agar_client): self.agar_client = agar_client self.player = Player() self.dispatcher = Dispatcher(packet_s2c, self) self.player_list = {} self.team_world = World() self.team_cids = set() self.session = None self.force_player_update = False config = configparser.ConfigParser({'address': 'localhost', 'port': '5000', 'password': '', 'update_rate': '0.1'}) config.read('tagar_client.cfg') self.update_rate = config.getfloat('Settings', 'update_rate') self.scheduler = sched.scheduler(time, sleep) self.scheduler.enter(self.update_rate, 1, self.recv_update) self.scheduler.enter(self.update_rate, 1, self.send_update) thread = threading.Thread(target=self.scheduler.run) thread.setDaemon(True) thread.start() address = config.get('Server', 'address') port = config.getint('Server', 'port') password = config.get('Server', 'password') self.connect(address, port, password) def connect(self, addr, port, password): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) # try to connect to server try: # Connect to server and send data sock.connect((addr, port)) buf = BufferStruct(opcode=100) # create challenge rand = random.randint(1, 254) m = hashlib.md5() m.update(password.encode('utf-16')) m.update(str(rand).encode('utf-8')) # send login challenge buf.push_null_str8(m.hexdigest()) buf.push_uint8(rand) # add protocol version buf.push_len_str8(PROTOCOL_VERSION) sock.send(buf.buffer) # Receive data from the server msg = sock.recv(1024) if msg is None or len(msg) == 0: msg = str() sid = None buf = BufferStruct(msg) while not buf.empty(): opcode = buf.pop_uint8() if opcode == 200: print("Connected to tagar server: %s:%d" % (addr, port)) sid = buf.pop_len_str8() login_ok = True if opcode == 201: print("[Tagar Server]: %s" % (buf.pop_len_str16(),)) if not sid: print("Connection to team server rejected!") sock.close() return self.session = Session(sid, sock) self.player = Player(self.session) self.force_player_update = True except socket.error: print("Could not connect to tagar server: %s:%d" % (addr, port)) def disconnect(self): self.session.disconnect() def recv_update(self): self.scheduler.enter(self.update_rate, 1, self.recv_update) if not self.session or not self.session.is_connected: return while 1: msg = self.session.pop_msg() if msg is None: return buf = BufferStruct(msg) while not buf.empty(): self.dispatcher.dispatch(buf) def send_update(self): self.scheduler.enter(self.update_rate, 1, self.send_update) if not self.session or not self.session.is_connected: return # collect player info self.player.pre_update_player_state() self.player.update_player_state(sid=self.session.sid, player=self.agar_client.player, party_token=self.agar_client.server_token) # collect world status self.player.world.pre_update_world() cells = self.agar_client.player.world.cells.copy() cells = {cid: c for cid, c in cells.items() if cid in self.player.own_ids or c.mass > 20 or c.is_food or c.is_ejected_mass} self.player.world.update_world(cells) # send update try: buf = BufferStruct() # player status if self.player.has_update() or self.force_player_update: buf.push_uint8(110) self.player.pack_player_update(buf) self.force_player_update = False # world status if self.player.world.has_update(): buf.push_uint8(111) self.player.world.pack_world_update(buf) if buf.buffer: self.session.sendall(buf.buffer) except socket.error: self.disconnect() def parse_player_list_update(self, buf): # update players for i in range(0, buf.pop_uint32()): p = Player() p.parse_player_update(buf) if str(self.session.sid) != p.sid: self.player_list[p.sid] = p # removed logged out players for i in range(0, buf.pop_uint32()): sid = buf.pop_len_str8() if sid in self.player_list: del self.player_list[sid] # update team cids self.team_cids = set() for p in self.player_list.values(): self.team_cids.update(p.own_ids) def parse_world_update(self, buf): self.team_world.parse_world_update(buf)
class Player: def __init__(self, session=None): self.session = session self.sid = str(session.sid) if session is not None else "" self.dispatcher = Dispatcher(packet_c2s, self) self.nick = str() self.position_x = 0.0 self.position_y = 0.0 self.total_mass = 0.0 self.own_ids = set() self.is_alive = False self.party_token = str() self.is_updated = False self.world = World() self.last_update_time = monotonic() def has_update(self): return self.is_updated def pre_update_player_state(self): self.is_updated = False def update_player_state(self, sid=-1, nick='', x=0.0, y=0.0, total_mass=0.0, own_ids=set(), is_alive=False, party_token='', player=None): if player: nick = player.nick x, y = player.center total_mass = player.total_mass own_ids = player.own_ids is_alive = player.is_alive party_token = party_token if len(party_token) == 5 else 'FFA' self.is_updated = (self.nick != nick or self.party_token != party_token or (self.is_alive and (self.position_x != x or self.position_y != y or self.total_mass != total_mass or self.own_ids != own_ids or self.is_alive != is_alive) ) ) self.sid = copy(sid) self.nick = copy(nick) self.position_x = copy(x) self.position_y = copy(y) self.total_mass = copy(total_mass) self.own_ids = own_ids.copy() self.is_alive = copy(is_alive) self.party_token = copy(party_token) self.last_update_time = monotonic() def handle_msgs(self): self.pre_update_player_state() self.world.pre_update_world() while self.session.has_new_msg(): self.parse_msg(self.session.pop_msg()) def parse_msg(self, msg): buf = BufferStruct(msg) while not buf.empty(): self.dispatcher.dispatch(buf) def parse_player_update(self, buf): self.pre_update_player_state() self.unpack_player_update(buf) self.last_update_time = monotonic() def parse_world_update(self, buf): self.world.parse_world_update(buf) def pack_player_update(self, buf=BufferStruct()): buf.push_len_str8(self.sid) buf.push_len_str16(self.nick) buf.push_float32(self.position_x) buf.push_float32(self.position_y) buf.push_float32(self.total_mass) buf.push_uint8(len(self.own_ids)) for cid in self.own_ids: buf.push_uint32(cid) buf.push_bool(self.is_alive) buf.push_null_str16(self.party_token) return buf def unpack_player_update(self, buf): sid = buf.pop_len_str8() nick = buf.pop_len_str16() x = buf.pop_float32() y = buf.pop_float32() total_mass = buf.pop_float32() own_ids = set() for i in range(buf.pop_uint8()): own_ids.add(buf.pop_uint32()) is_alive = buf.pop_bool() party_token = buf.pop_null_str16() self.update_player_state(sid, nick, x, y, total_mass, own_ids, is_alive, party_token) return buf