예제 #1
0
    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)
예제 #2
0
    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()
예제 #3
0
    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)))
예제 #4
0
    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
예제 #5
0
 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
예제 #6
0
    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
예제 #7
0
    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)))
예제 #8
0
    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
예제 #9
0
    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]
예제 #10
0
    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
예제 #11
0
    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]
예제 #12
0
    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
예제 #13
0
    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)
예제 #14
0
    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)
예제 #15
0
    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
예제 #16
0
 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
예제 #17
0
    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
예제 #18
0
 async def process(self):
     # TODO: correctly process disconnect
     PlayerManager().set(self.temp_ref.player).save()
     return None, None