def handle_SetCompression(self, packet): """Threshold (VarInt): Maximum size of a packet before it is compressed""" threshold, packet = ParseVarInt(packet, consume=True) del threshold print("Login.SetCompression") self.compression = True return packet
def run(self): print("MCBot running...") self.send_HandShake() self.send_LoginStart() packet = [] while True: data = self.recv(1) if data: data = data[0] packet.append(data) # If we see that we got VarInt, start parsing if data & 0b10000000 == 0: length = ParseVarInt(packet) # Hack to make sure socket gets all bytes packet = [] while len(packet) < length: packet.append(self.recv(1)[0]) assert (len(packet) == length ), "Length is somehow different! (%s != %s)" % ( len(packet), length) # Now that we have the packet handle it try: self.handle_packet(packet) except: print("FAIL: ", "".join([chr(x) for x in packet])) self.handle_packet(packet) packet = []
def handle_UpdateHealth(self, packet): health, packet = ParseFloat(packet, consume=True) food, packet = ParseVarInt(packet, consume=True) saturation, packet = ParseFloat(packet, consume=True) print("Play.UpdateHealth: (%s, %s, %s)" % (health, food, saturation)) # pylint: disable=no-member self.respawn() return packet
def handle_PlayerInfo(self, packet): action, packet = ParseVarInt(packet, consume=True) number_of_players, packet = ParseVarInt(packet, consume=True) if number_of_players: players = int(len(packet) / number_of_players) if action == 0: self._player_action_zero(players, packet) elif action == 1: # this is game mode pass elif action == 2: # this is ping info pass elif action == 4: self._player_action_four(players, packet) else: print("Play.PlayerInfo") print(action) hex_print(packet) return []
def handle_EntityTeleport(self, packet): entity_id, packet = ParseVarInt(packet, consume=True) x, packet = ParseDouble(packet, consume=True) y, packet = ParseDouble(packet, consume=True) z, packet = ParseDouble(packet, consume=True) # Not handling yaw, pitch, or on_ground packet = packet[4:] # pylint: disable=not-context-manager with self.lock: if entity_id in self.entities: self.entities[entity_id].set_position(x, y, z) return packet
def handle_packet(self, packet): """Parse packet id and call appropriate handler""" if self.compression: compression_len, packet = ParseVarInt(packet, consume=True) # if we have compressed data decompress it if compression_len != 0: packet = zlib.decompress(bytearray(packet)) packet_id, packet = ParseVarInt(packet, consume=True) try: packet_id = str(self.state(packet_id)) except ValueError: # print("Unknown packet ID %s for state %s" % (hex(packet_id), self.state)) pass try: func = getattr(self, "handle_" + packet_id.split(".")[1]) packet = func(packet=packet) assert len(packet) == 0 except AttributeError: # print("Unknown packet: %s" % packet) pass
def handle_ChatMessage(self, packet): length, packet = ParseVarInt(packet, consume=True) message, packet = ParseString(packet, length, consume=True) message = json.loads(message) position = packet[0] packet = packet[1:] del position txt = message["with"][-1] if isinstance(txt, dict): txt = txt["text"] if txt.startswith("!"): # pylint: disable=no-member self.bot_command(txt[1:]) return packet
def handle_EntityProperties(self, packet): entity_id, packet = ParseVarInt(packet, consume=True) number_of_properties, packet = ParseInt(packet, consume=True) stats = [] for _ in range(number_of_properties): key_len = packet[0] key, packet = ParseString(packet[1:], key_len, consume=True) value, packet = ParseDouble(packet, consume=True) number_of_mods, packet = ParseVarInt(packet, consume=True) mods = [] for _ in range(number_of_mods): uuid, packet = ParseUUID(packet, consume=True) amount, packet = ParseDouble(packet, consume=True) operation = packet[0] packet = packet[1:] mods.append([uuid, amount, operation]) mod_amount = 0 for mod in mods: uuid, amount, operation = mod del uuid if operation == 0: mod_amount += amount else: print("Play.EntityProperties: ", operation, amount) value += mod_amount stats.append((key, value)) # pylint: disable=not-context-manager with self.lock: if entity_id in self.entities: ent = self.entities[entity_id] ent.set_properties(stats) name = self.names[ent.uuid] ent.name = name return packet
def handle_PlayerPositionAndLook(self, packet): x, packet = ParseDouble(packet, consume=True) y, packet = ParseDouble(packet, consume=True) z, packet = ParseDouble(packet, consume=True) yaw, packet = ParseFloat(packet, consume=True) pitch, packet = ParseFloat(packet, consume=True) # Instead of parsing flags we just skip a byte # flags, packet = ParseByte(packet, consume=True) packet = packet[1:] teleport_id, packet = ParseVarInt(packet, consume=True) # print("Play.PlayerPositionAndLook (x:%s, y:%s, z:%s, teleport:%s)" % (x, y, z, teleport_id)) self.position = [x, y, z] self.pitch = pitch self.yaw = yaw # pylint: disable=no-member self.send_TeleportConfirm(teleport_id) return packet
def handle_SpawnPlayer(self, packet): entity_id, packet = ParseVarInt(packet, consume=True) uuid, packet = ParseUUID(packet, consume=True) x, packet = ParseDouble(packet, consume=True) y, packet = ParseDouble(packet, consume=True) z, packet = ParseDouble(packet, consume=True) # pylint: disable=not-context-manager with self.lock: if entity_id in self.entities: self.entities[entity_id].set_position(x, y, z) else: ent = Entity(uuid) ent.set_position(x, y, z) if ent.uuid in self.names: name = self.names[ent.uuid] ent.name = name self.entities[entity_id] = ent return []
def handle_EntityRelativeMove(self, packet): entity_id, packet = ParseVarInt(packet, consume=True) delta_x, packet = ParseShort(packet, consume=True) delta_y, packet = ParseShort(packet, consume=True) delta_z, packet = ParseShort(packet, consume=True) # Not handling on_ground packet = packet[1:] # Calculating relative changes to coords # pylint: disable=not-context-manager with self.lock: if entity_id in self.entities and self.entities[entity_id].position: x, y, z = self.entities[entity_id].position div = 32 * 128 delta_x = delta_x / div delta_y = delta_y / div delta_z = delta_z / div new_x = x + delta_x new_y = y + delta_y new_z = z + delta_z self.entities[entity_id].set_position(new_x, new_y, new_z) # print("Play.EntityRelativeMove (%s: x:%s, y:%s, z:%s)" % (entity_id, x, y, z)) return []