def _broadcast(self, **kwargs) -> None: opcode: WorldOpCode = kwargs.pop('opcode') packets: List[bytes] = kwargs.pop('packets') regions: Dict[int, Region] = kwargs.pop('regions') player: Player = self.connection.player current_region: Region = regions.get(player.region.id) if current_region is None: return None current_node: OctreeNode = player.get_current_node() if not current_node: return None # we get parent of parent because some of nearest nodes can lay in the another parent node_to_notify: OctreeNode = current_node.parent_node.parent_node guids = OctreeNodeManager.get_guids(node_to_notify) guids = [guid for guid in guids if not guid == player.guid] if not guids: return None targets_to_notify: List[Player] = [ player for player in current_region.players if player.guid in guids ] if not targets_to_notify: return None for packet in packets: PlayerManager.broadcast(opcode, packet, targets_to_notify)
def create_target_packets(targets: List[Player]) -> List[bytes]: update_flags = (UpdateObjectFlags.UPDATEFLAG_HIGHGUID.value | UpdateObjectFlags.UPDATEFLAG_LIVING.value | UpdateObjectFlags.UPDATEFLAG_HAS_POSITION.value) targets = targets.copy() with PlayerManager() as head_player_mgr: head_player_mgr.init_update_packet_builder( object_update_type=ObjectUpdateType.CREATE_OBJECT2, update_flags=update_flags, update_object=targets.pop(0)) batch = head_player_mgr.create_batch(PLAYER_SPAWN_FIELDS) head_player_mgr.add_batch(batch) if targets: for target in targets: with PlayerManager() as player_mgr: player_mgr.init_update_packet_builder( object_update_type=ObjectUpdateType.CREATE_OBJECT2, update_flags=update_flags, update_object=target) batch = player_mgr.create_batch(PLAYER_SPAWN_FIELDS) head_player_mgr.add_batch(batch) return head_player_mgr.build_update_packet().get_update_packets()
def _notify_nearest_players(player: Player, targets: List[Player] = None, **kwargs): opcode, packet = kwargs.pop('movement_packet', (None, None)) text_message_packet = kwargs.pop('text_message_packet', None) if opcode and packet: packet = targets.pop(0).packed_guid + packet asyncio.ensure_future( QueuesRegistry.movement_packets_queue.put((player.name, packet, opcode)) ) elif text_message_packet: asyncio.ensure_future( QueuesRegistry.text_message_packets_queue.put((player.name, text_message_packet)) ) else: update_flags = ( UpdateObjectFlags.UPDATEFLAG_HIGHGUID.value | UpdateObjectFlags.UPDATEFLAG_LIVING.value | UpdateObjectFlags.UPDATEFLAG_HAS_POSITION.value ) targets = targets.copy() object_update_type = kwargs.pop('object_update_type', ObjectUpdateType.CREATE_OBJECT2) with PlayerManager() as head_player_mgr: RegionManager._init_update_packet_builder( head_player_mgr, object_update_type=object_update_type, update_flags=update_flags, update_object=targets.pop(0) ) batch = head_player_mgr.create_batch(RegionManager.PLAYER_SPAWN_FIELDS) head_player_mgr.add_batch(batch) if targets: for target in targets: with PlayerManager() as player_mgr: RegionManager._init_update_packet_builder( player_mgr, object_update_type=ObjectUpdateType.CREATE_OBJECT2, update_flags=update_flags, update_object=target ) batch = player_mgr.create_batch(RegionManager.PLAYER_SPAWN_FIELDS) head_player_mgr.add_batch(batch) update_packets = head_player_mgr.build_update_packet().get_update_packets() asyncio.ensure_future(QueuesRegistry.update_packets_queue.put((player.name, update_packets)))
async def process(self): region_id = unpack('<I', self.packet[-4:])[0] if not self.temp_ref.player.region.region_id == region_id: region = RegionManager().get_region(region_id=region_id) self.temp_ref.player.region = region player_mgr = PlayerManager() player_mgr.set(self.temp_ref.player).save() Logger.notify('[Zone Update]: saving player') return None, None
def _load_player(self) -> None: # size (first 2 bytes) - opcode (next 4 bytes) - guid (remaining bytes) guid = int.from_bytes(self.data, 'little') with PlayerManager() as player_mgr: player_mgr.load(id=guid) player = player_mgr.player self.connection.player = player
async def process(self): with PlayerManager() as player_mgr: player_mgr.set(self.temp_ref.player).save() response = pack('<IB', 0, 0) return WorldOpCode.SMSG_LOGOUT_RESPONSE, response
async def refresh_players(self, current_player: Player): for region in self.regions: region.set_online_players(current_player) current_region = next(region for region in self.regions if region.id == current_player.region.id) online_players = current_region.get_online_players() players = [ online_players[name] for name in online_players if not name == current_player.name ] # finally building packet for player that contains player list movement_flags = (UpdateObjectFlags.UPDATEFLAG_HIGHGUID.value | UpdateObjectFlags.UPDATEFLAG_LIVING.value | UpdateObjectFlags.UPDATEFLAG_HAS_POSITION.value) update_packets = [] for player in players: with PlayerManager() as player_mgr: player_mgr.set(player) player_mgr.movement.set_update_flags(movement_flags) batch_builder = player_mgr.prepare() \ .build_update_packet(RegionManager.PLAYER_SPAWN_FIELDS) update_packets.append(batch_builder) asyncio.ensure_future( QueuesRegistry.update_packets_queue.put( (current_player.name, update_packets)))
async def process(self): with PlayerManager() as player_mgr: player_mgr.set_object_update_type( object_update_type=ObjectUpdateType.CREATE_OBJECT2) # be careful, set_update_flags should be called after prepare(), because of update_packet_builder init player_mgr.set(self.player).prepare().set_update_flags( self.update_flags) # add fields with offset before create update packet skills_count = len(self.player.skills) for skill_index in range(skills_count): offset = skill_index * 3 skill: PlayerSkill = self.player.skills[skill_index] player_mgr.add_field(PlayerField.SKILL_INFO_1_ID, skill.skill_template.entry, offset=offset) player_mgr.add_field(PlayerField.SKILL_INFO_1_LEVEL, skill.skill_template.min, offset=offset + 1) player_mgr.add_field(PlayerField.SKILL_INFO_1_STAT_LEVEL, skill.skill_template.max, offset=offset + 2) batch = player_mgr.create_batch(PlayerSpawn.SPAWN_FIELDS) response = player_mgr.add_batch( batch).build_update_packet().get_update_packets() return WorldOpCode.SMSG_UPDATE_OBJECT, response
async def process(self) -> tuple: data = self._parse_packet() try: with PlayerManager() as player_mgr: player_mgr.new(name=data['name'], race=data['race'], char_class=data['char_class'], gender=data['gender'], skin=data['skin'], face=data['face'], hair_style=data['hair_style'], hair_color=data['hair_color'], facial_hair=data['facial_hair'], account=self.connection.account) Logger.notify(f'Character \"{data["name"]}\" created') response = pack( '<B', CharCreateResponseCode.CHAR_CREATE_SUCCESS.value) return WorldOpCode.SMSG_CHAR_CREATE, [response] except IntegrityError: response = pack( '<B', CharCreateResponseCode.CHAR_CREATE_NAME_IN_USE.value) return WorldOpCode.SMSG_CHAR_CREATE, [response]
async def process(self) -> tuple: # TODO: correctly process disconnect with PlayerManager() as player_mgr: player_mgr.set(self.connection.player).save() await QueuesRegistry.disconnect_queue.put(self.connection.player.name) await QueuesRegistry.remove_player_queue.put(self.connection.player) return None, None
async def process(self) -> tuple: with PlayerManager() as player_mgr: player_mgr.set(self.connection.player).save() response = pack( '<IB', 0, 0 ) return WorldOpCode.SMSG_LOGOUT_RESPONSE, [response]
async def process(self) -> tuple: # identifier = unpack('<I', self.data[-4:])[0] identifier = unpack('<I', self.data[:4])[0] if not self.connection.player.region.identifier == identifier: region = RegionManager().get_region(identifier=identifier) self.connection.player.region = region with PlayerManager() as player_mgr: player_mgr.set(self.connection.player).save() Logger.notify('[Zone Update]: saving player') return None, None
def broadcast(**kwargs) -> None: opcode: WorldOpCode = kwargs.pop('opcode') packets: List[bytes] = kwargs.pop('packets') regions: Dict[int, Region] = kwargs.pop('regions') for region in regions.values(): root_node: OctreeNode = region.get_octree() guids = OctreeNodeManager.get_guids(root_node) if not guids: continue targets_to_notify: List[Player] = [ player for player in region.players if player.guid in guids ] if not targets_to_notify: continue for packet in packets: PlayerManager.broadcast(opcode, packet, targets_to_notify)
async def process(self): data = self._parse_packet() PlayerManager(temp_ref=self.temp_ref).new( name=data['name'], race=data['race'], char_class=data['char_class'], gender=data['gender'], skin=data['skin'], face=data['face'], hair_style=data['hair_style'], hair_color=data['hair_color'], facial_hair=data['facial_hair'], ).set_stats().save() Logger.notify('Character created') return WorldOpCode.SMSG_CHAR_CREATE, pack( '<B', CharCreateResponseCode.CHAR_CREATE_SUCCESS.value)
async def process(self) -> tuple: with PlayerManager() as player_mgr: player_mgr.init_update_packet_builder( object_update_type=ObjectUpdateType.CREATE_OBJECT2, update_flags=self.update_flags, update_object=self.connection.player) # add fields with offset before create update packet skills_count = len(self.connection.player.skills) for skill_index in range(skills_count): offset = skill_index * 3 skill: PlayerSkill = self.connection.player.skills[skill_index] player_mgr.add_field(PlayerField.SKILL_INFO_1_ID, skill.skill_template.entry, offset=offset) player_mgr.add_field(PlayerField.SKILL_INFO_1_LEVEL, skill.skill_template.min, offset=offset + 1) player_mgr.add_field(PlayerField.SKILL_INFO_1_STAT_LEVEL, skill.skill_template.max, offset=offset + 2) batch: bytes = player_mgr.create_batch(self.spawn_fields) packets: List[bytes] = player_mgr\ .add_batch(batch)\ .build_update_packet()\ .get_update_packets() ensure_future( QueuesRegistry.broadcast_callback_queue.put(( WorldOpCode.SMSG_UPDATE_OBJECT, packets, self._broadcast, ))) return WorldOpCode.SMSG_UPDATE_OBJECT, packets
def _load_player(self): # size (first 2 bytes) - opcode (next 4 bytes) - guid (remaining bytes) guid = int.from_bytes(self.packet[6:], 'little') with PlayerManager() as player_mgr: player_mgr.load(id=guid) self.temp_ref.player = player_mgr.player
async def process(self): with PlayerManager() as player_mgr: response = player_mgr\ .set(self.player).prepare().build_update_packet(PlayerSpawn.SPAWN_FIELDS).get_update_packet(build=True) return WorldOpCode.SMSG_UPDATE_OBJECT, response
async def process(self): # TODO: correctly process disconnect PlayerManager().set(self.temp_ref.player).save() return None, None