def leave_party(self, player_guid, force_disband=False, is_kicked=False): disband = player_guid == self.group.leader_guid or len( self.members) == 2 or force_disband was_formed = self.is_party_formed() # Group was disbanded before even existing. if disband and player_guid == self.group.leader_guid and len( self.members) == 0: leader_player = WorldSessionStateHandler.find_player_by_guid( self.group.leader_guid) if leader_player: leader_player.group_manager = None leader_player.has_pending_invite = False else: for member in list(self.members.values()): # Avoid mutability. if disband or member.guid == player_guid: member_player = WorldSessionStateHandler.find_player_by_guid( member.guid) if member_player: member_player.has_pending_group_invite = False member_player.group_manager = None member_player.group_status = WhoPartyStatus.WHO_PARTY_STATUS_NOT_IN_PARTY if member.guid == self.group.leader_guid: GroupManager._remove_leader_flag(member) if not disband: self._set_previous_looter(member.guid) RealmDatabaseManager.group_remove_member(member) self.members.pop(member.guid) if was_formed and member_player and disband and not is_kicked and member.guid != player_guid: disband_packet = PacketWriter.get_packet( OpCode.SMSG_GROUP_DESTROYED) member_player.enqueue_packet(disband_packet) elif was_formed and member_player and disband and member.guid != player_guid: disband_packet = PacketWriter.get_packet( OpCode.SMSG_GROUP_DESTROYED) member_player.enqueue_packet(disband_packet) elif was_formed and member_player and not is_kicked: GroupManager.send_group_operation_result( member_player, PartyOperations.PARTY_OP_LEAVE, member_player.player.name, PartyResults.ERR_PARTY_RESULT_OK) if member_player and is_kicked and member.guid == player_guid: # 'You have been removed from the group.' message packet = PacketWriter.get_packet( OpCode.SMSG_GROUP_UNINVITE) member_player.enqueue_packet(packet) if disband: self.flush() else: self.send_update()
def _build_party_member_stats(group_member): player_mgr = WorldSessionStateHandler.find_player_by_guid( group_member.guid) character = None # If player is offline, build stats based on db information. if not player_mgr or not player_mgr.online: player_mgr = None character = RealmDatabaseManager.character_get_by_guid( group_member.guid) data = pack( '<Q2IB6I3f', player_mgr.guid if player_mgr else character.guid, player_mgr.health if player_mgr else 0, player_mgr.max_health if player_mgr else 0, player_mgr.power_type if player_mgr else 0, player_mgr.get_power_type_value() if player_mgr else 0, player_mgr.get_max_power_value() if player_mgr else 0, player_mgr.level if player_mgr else character.level, player_mgr.map_ if player_mgr else character.map, # Client expects an AreaNumber from AreaTable, not a zone id. MapManager.get_area_number_by_zone_id( player_mgr.zone if player_mgr else character.zone), player_mgr.class_ if player_mgr else character.class_, player_mgr.location.x if player_mgr else character.position_x, player_mgr.location.y if player_mgr else character.position_y, player_mgr.location.z if player_mgr else character.position_z, ) return PacketWriter.get_packet(OpCode.SMSG_PARTY_MEMBER_STATS, data)
def _remove_leader_flag(member): player_mgr = WorldSessionStateHandler.find_player_by_guid(member.guid) if player_mgr: player_mgr.player.extra_flags &= ~PlayerFlags.PLAYER_FLAGS_GROUP_LEADER player_mgr.player_bytes_2 = unpack('<I', pack('<4B', player_mgr.player.extra_flags, player_mgr.player.facialhair, player_mgr.player.bankslots, 0))[0] player_mgr.set_uint32(PlayerFields.PLAYER_BYTES_2, player_mgr.player_bytes_2) player_mgr.set_dirty()
def send_update(self): for member in list(self.members.keys()): player_mgr = WorldSessionStateHandler.find_player_by_guid(member) if player_mgr: player_mgr.enqueue_packet(self._build_group_list(player_mgr)) self.send_party_members_stats()
def send_packet_to_members(self, packet, ignore=None, source=None, use_ignore=False, exclude=None, surrounding_only=False): if surrounding_only and source: surrounding_players = MapManager.get_surrounding_players( source).values() members = [ self.members[player.guid] for player in surrounding_players if player.guid in self.members ] else: members = self.members.values() for member in members: if exclude and member.guid == exclude.guid: continue player_mgr = WorldSessionStateHandler.find_player_by_guid( member.guid) if not player_mgr or not player_mgr.online: continue if ignore and player_mgr.guid in ignore: continue if use_ignore and source and player_mgr.friends_manager.has_ignore( source.guid): continue player_mgr.enqueue_packet(packet)
def set_guild_master(self, player_guid): member = self.members[player_guid] previous_gm = self.guild_master member.rank = int(GuildRank.GUILDRANK_GUILD_MASTER) previous_gm.rank = int(GuildRank.GUILDRANK_OFFICER) if previous_gm: data = pack('<2B', GuildEvents.GUILD_EVENT_LEADER_CHANGED, 2) name_bytes = PacketWriter.string_to_bytes( previous_gm.character.name) data += pack(f'<{len(name_bytes)}s', name_bytes) name_bytes = PacketWriter.string_to_bytes(member.character.name) data += pack(f'<{len(name_bytes)}s', name_bytes) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) self.update_db_guild_members() player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) if player_mgr: player_mgr.set_uint32(PlayerFields.PLAYER_GUILDRANK, member.rank) player_mgr.set_dirty()
def remove_member(self, player_guid): member = self.members[player_guid] guild_master = self.guild_master data = pack('<2B', GuildEvents.GUILD_EVENT_REMOVED, 2) target_name_bytes = PacketWriter.string_to_bytes(member.character.name) data += pack( f'<{len(target_name_bytes)}s', target_name_bytes ) remover_name_bytes = PacketWriter.string_to_bytes(guild_master.character.name) data += pack( f'<{len(remover_name_bytes)}s', remover_name_bytes ) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) # Pop it at the end, so he gets the above message. RealmDatabaseManager.guild_remove_member(member) player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) self.members.pop(player_guid) if player_mgr: self.build_update(player_mgr, unset=True) player_mgr.guild_manager = None player_mgr.set_dirty()
def create_guild(player_mgr, guild_name, petition=None): if not TextChecker.valid_text(guild_name, is_guild=True): GuildManager.send_guild_command_result(player_mgr, GuildTypeCommand.GUILD_CREATE_S, '', GuildCommandResults.GUILD_NAME_INVALID) return False if guild_name in GuildManager.GUILDS or not petition and RealmDatabaseManager.guild_petition_get_by_name(guild_name): GuildManager.send_guild_command_result(player_mgr, GuildTypeCommand.GUILD_CREATE_S, guild_name, GuildCommandResults.GUILD_NAME_EXISTS) return False if player_mgr.guild_manager: GuildManager.send_guild_command_result(player_mgr, GuildTypeCommand.GUILD_CREATE_S, '', GuildCommandResults.GUILD_ALREADY_IN_GUILD) return False guild = GuildManager._create_guild("", guild_name, -1, -1, -1, -1, -1, player_mgr.guid) player_mgr.guild_manager = GuildManager(guild) player_mgr.guild_manager.add_new_member(player_mgr, is_guild_master=True) if petition: for member_signer in petition.characters: member = WorldSessionStateHandler.find_player_by_guid(member_signer.guid) if member: player_mgr.guild_manager.add_new_member(member, False) else: offline_member = RealmDatabaseManager.character_get_by_guid(member_signer.guid) if offline_member: player_mgr.guild_manager.add_new_offline_member(offline_member) return True
def _remove_leader_flag(member): player_mgr = WorldSessionStateHandler.find_player_by_guid(member.guid) if player_mgr: player_mgr.player.extra_flags &= ~PlayerFlags.PLAYER_FLAGS_GROUP_LEADER player_mgr.player_bytes_2 = player_mgr.get_player_bytes_2() player_mgr.set_uint32(PlayerFields.PLAYER_BYTES_2, player_mgr.player_bytes_2)
def handle(world_session, socket, reader): if len(reader.data) >= 16: # Avoid handling empty petition offer packet. petition_item_guid, target_player_guid = unpack('<2Q', reader.data[:16]) target_player_mgr = WorldSessionStateHandler.find_player_by_guid(target_player_guid) if petition_item_guid > 0: if not target_player_mgr: GuildManager.send_guild_command_result(world_session.player_mgr, GuildTypeCommand.GUILD_INVITE_S, 'Player', GuildCommandResults.GUILD_PLAYER_NOT_FOUND) elif target_player_mgr.guild_manager: GuildManager.send_guild_command_result(world_session.player_mgr, GuildTypeCommand.GUILD_INVITE_S, target_player_mgr.player.name, GuildCommandResults.GUILD_ALREADY_IN_GUILD) if target_player_mgr.team != world_session.player_mgr.team: GuildManager.send_guild_command_result(world_session.player_mgr, GuildTypeCommand.GUILD_INVITE_S, '', GuildCommandResults.GUILD_NOT_ALLIED) else: petition = PetitionManager.get_petition(petition_item_guid) if petition: packet = PetitionManager.build_signatures_packet(petition) target_player_mgr.enqueue_packet(packet) else: PetitionManager.send_petition_sign_result(world_session.player_mgr, PetitionError.PETITION_UNKNOWN_ERROR) return 0
def demote_rank(self, player_guid): member = self.members[player_guid] if member.rank == GuildRank.GUILDRANK_GUILD_MASTER: return False if member.rank == GuildRank.GUILDRANK_INITIATE: # Use initiate as lowest for now return False else: member.rank += 1 data = pack('<2B', GuildEvents.GUILD_EVENT_DEMOTION, 2) target_name_bytes = PacketWriter.string_to_bytes(member.character.name) data += pack(f'<{len(target_name_bytes)}s', target_name_bytes) rank_name = GuildRank(member.rank).name.split('_')[1].capitalize() rank_name_bytes = PacketWriter.string_to_bytes(rank_name) data += pack(f'<{len(rank_name_bytes)}s', rank_name_bytes) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) player_mgr = WorldSessionStateHandler.find_player_by_guid(member.guid) if player_mgr: player_mgr.set_uint32(PlayerFields.PLAYER_GUILDRANK, member.rank) player_mgr.set_dirty() self.update_db_guild_members() return True
def send_update_to_friends(self): have_me_as_friend = RealmDatabaseManager.character_get_friends_of( self.owner.guid) for friend in have_me_as_friend: player_mgr = WorldSessionStateHandler.find_player_by_guid( friend.guid) if player_mgr: player_mgr.friends_manager.send_friends()
def handle_permanent_enchant(casting_spell, effect, caster, target, is_temporary=False): if caster.get_type_id() != ObjectTypeIds.ID_PLAYER: return # Calculate slot, duration and charges. enchantment_slot = EnchantmentSlots.PermanentSlot if not is_temporary else EnchantmentSlots.TemporarySlot duration = 0 charges = 0 if is_temporary: # Temporary enchantments from professions (enchanting) have a duration of 1h while others have 30min. duration = 30 * 60 if not casting_spell.spell_entry.CastUI else 60 * 60 charges = int( WorldDatabaseManager.spell_enchant_charges_get_by_spell( casting_spell.spell_entry.ID)) owner_player = WorldSessionStateHandler.find_player_by_guid( target.get_owner_guid()) if not owner_player: return # If this enchantment is being applied on a trade, update trade status with proposed enchant. # Enchant will be applied after trade is accepted. if owner_player != caster: if caster.trade_data and caster.trade_data.other_player and caster.trade_data.other_player.trade_data: # Get the trade slot for the item being enchanted. trade_slot = caster.trade_data.other_player.trade_data.get_slot_by_item( target) # Update proposed enchantment on caster. caster.trade_data.set_proposed_enchant( trade_slot, casting_spell.spell_entry.ID, enchantment_slot, effect.misc_value, duration, charges) # Update proposed enchantment on receiver. caster.trade_data.other_player.trade_data.set_proposed_enchant( trade_slot, casting_spell.spell_entry.ID, enchantment_slot, effect.misc_value, duration, charges) # Update trade status, this will propagate to both players. caster.trade_data.update_trade_status() return # Apply permanent enchantment. owner_player.enchantment_manager.set_item_enchantment( target, enchantment_slot, effect.misc_value, duration, charges) caster.skill_manager.handle_profession_skill_gain_chance( casting_spell.spell_entry.ID) # Save item. target.save()
def _target_or_self(world_session): if world_session.player_mgr.current_selection \ and world_session.player_mgr.current_selection != world_session.player_mgr.guid: player_mgr = WorldSessionStateHandler.find_player_by_guid( world_session.player_mgr.current_selection) if player_mgr: return player_mgr return world_session.player_mgr
def send_invite_decline(self, player_name): player_mgr = WorldSessionStateHandler.find_player_by_guid( self.group.leader_guid) if player_mgr: name_bytes = PacketWriter.string_to_bytes(player_name) data = pack(f'<{len(name_bytes)}s', name_bytes) packet = PacketWriter.get_packet(OpCode.SMSG_GROUP_DECLINE, data) player_mgr.enqueue_packet(packet)
def send_offline_notification(self): have_me_as_friend = RealmDatabaseManager.character_get_friends_of(self.owner.guid) for friend in have_me_as_friend: player_mgr = WorldSessionStateHandler.find_player_by_guid(friend.guid) if player_mgr and not player_mgr.friends_manager.has_ignore(self.owner.guid): data = pack('<BQB', FriendResults.FRIEND_OFFLINE, self.owner.guid, 0) packet = PacketWriter.get_packet(OpCode.SMSG_FRIEND_STATUS, data) player_mgr.session.enqueue_packet(packet) player_mgr.friends_manager.send_friends()
def send_friends(self): data = pack('<B', len(self.friends)) for friend in self.friends: player_mgr = WorldSessionStateHandler.find_player_by_guid(friend) if player_mgr: data += pack('<QB3I', player_mgr.guid, 1, player_mgr.zone, player_mgr.level, player_mgr.player.class_) packet = PacketWriter.get_packet(OpCode.SMSG_FRIEND_LIST, data) self.owner.session.request.sendall(packet)
def send_ignores(self): data = pack('<B', len(self.ignores)) for ignore in self.ignores.values(): player_mgr = WorldSessionStateHandler.find_player_by_guid(ignore) if player_mgr: data += pack('<Q', player_mgr.guid) packet = PacketWriter.get_packet(OpCode.SMSG_IGNORE_LIST, data) self.owner.session.request.sendall(packet)
def send_update(self): leader_name_bytes = PacketWriter.string_to_bytes( self.members[self.group.leader_guid].character.name) leader = WorldSessionStateHandler.find_player_by_guid( self.group.leader_guid) # Header data = pack( f'<I{len(leader_name_bytes)}sQB', len(self.members), leader_name_bytes, self.group.leader_guid, 1 if leader and leader.online else 0 # If party leader is online or not ) # Fill all group members. for member in self.members.values(): if member.guid == self.group.leader_guid: continue player_mgr = WorldSessionStateHandler.find_player_by_guid( member.guid) member_name_bytes = PacketWriter.string_to_bytes( member.character.name) data += pack( f'<{len(member_name_bytes)}sQB', member_name_bytes, member.guid, 1 if player_mgr and player_mgr.online else 0, # If member is online or not ) data += pack( '<BQ', self.group.loot_method, self.group.loot_master # Master Looter guid ) packet = PacketWriter.get_packet(OpCode.SMSG_GROUP_LIST, data) self.send_packet_to_members(packet) self.send_party_members_stats()
def get_contained(self): if not self.item_instance: return 0 if self.item_instance.bag == InventorySlots.SLOT_INBACKPACK: return self.item_instance.owner else: player_mgr = WorldSessionStateHandler.find_player_by_guid(self.item_instance.owner) if player_mgr: return player_mgr.inventory.get_container(self.item_instance.bag).guid return 0
def player_info(world_session, args): # Because you can select party members on different maps, we search in the entire session pool player = WorldSessionStateHandler.find_player_by_guid( world_session.player_mgr.current_selection) if player: return 0, '[%s] - Guid: %u, Account ID: %u, Account name: %s' % ( player.player.name, player.guid & ~HighGuid.HIGHGUID_PLAYER, player.session.account_mgr.account.id, player.session.account_mgr.account.name) return -1, 'error retrieving player info.'
def un_invite_player(self, player_guid, target_player_guid): player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) if not player_mgr: return if target_player_guid not in self.members: GroupManager.send_group_operation_result(player_mgr, PartyOperations.PARTY_OP_LEAVE, '', PartyResults.ERR_TARGET_NOT_IN_YOUR_GROUP_S) return elif self.group.leader_guid != player_guid: GroupManager.send_group_operation_result(player_mgr, PartyOperations.PARTY_OP_LEAVE, '', PartyResults.ERR_NOT_LEADER) return self.leave_party(target_player_guid, is_kicked=True)
def remove_invitation(self, player_guid): if player_guid in self.invites: self.invites.pop(player_guid, None) player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) if player_mgr: player_mgr.has_pending_group_invite = False player_mgr.group_manager = None player_mgr.group_status = WhoPartyStatus.WHO_PARTY_STATUS_NOT_IN_PARTY if len(self.members) <= 1 and len(self.invites) == 0: self.leave_party(self.group.leader_guid, force_disband=True)
def add_friend(self, player_guid): if player_guid not in self.friends: self.friends[player_guid] = self._create_friend(player_guid) player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) RealmDatabaseManager.character_add_friend(self.friends[player_guid]) status = FriendResults.FRIEND_ADDED_ONLINE if player_mgr else FriendResults.FRIEND_ADDED_OFFLINE data = pack('<BQ', status, player_guid) if player_mgr and player_mgr.online: # Player is online. data += pack('<B3I', 1, player_mgr.zone, player_mgr.level, player_mgr.player.class_) self.owner.session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_FRIEND_STATUS, data)) self.send_friends()
def handle(world_session, socket, reader): if len(reader.data) >= 8: # Avoid handling empty petition sign packet. petition_guid = unpack('<Q', reader.data[:8])[0] if petition_guid > 0: petition = PetitionManager.get_petition(petition_guid) petition_owner = WorldSessionStateHandler.find_player_by_guid( petition.owner_guid) if petition and petition_owner: PetitionManager.sign_petition(petition, world_session.player_mgr, petition_owner) return 0
def send_friends(self): friends_list = [f for f in self.friends.values() if not f.ignore] data = pack('<B', len(friends_list)) for entry in friends_list: player_mgr = WorldSessionStateHandler.find_player_by_guid(entry.friend) if player_mgr and player_mgr.online: self.owner.session.enqueue_packet(NameQueryHandler.get_query_details(player_mgr.player)) data += pack('<QB3I', player_mgr.guid, 1, player_mgr.zone, player_mgr.level, player_mgr.player.class_) else: data += pack('QB', entry.friend, 0) # 0 = Offline packet = PacketWriter.get_packet(OpCode.SMSG_FRIEND_LIST, data) self.owner.session.enqueue_packet(packet)
def _build_group_list(self, player_mgr): leader_name_bytes = PacketWriter.string_to_bytes( self.members[self.group.leader_guid].character.name) leader = WorldSessionStateHandler.find_player_by_guid( self.group.leader_guid) # Members excluding self unless self == leader member_count = len( self.members ) if player_mgr.guid == self.group.leader_guid else len( self.members) - 1 # Header data = pack(f'<I{len(leader_name_bytes)}sQB', member_count, leader_name_bytes, self.group.leader_guid, 1 if leader and leader.online else 0) # Fill all group members except self or leader. for member in list(self.members.values()): if member.guid == self.group.leader_guid or member.guid == player_mgr.guid: continue member_player = WorldSessionStateHandler.find_player_by_guid( member.guid) member_name_bytes = PacketWriter.string_to_bytes( member.character.name) data += pack(f'<{len(member_name_bytes)}sQB', member_name_bytes, member.guid, 1 if member_player and member_player.online else 0) data += pack( '<BQ', self.group.loot_method, self.group.loot_master # Master Looter guid ) return PacketWriter.get_packet(OpCode.SMSG_GROUP_LIST, data)
def try_add_member(self, player_mgr, invite): # Check if we have space. if self.is_full(): GroupManager.send_group_operation_result( player_mgr, PartyOperations.PARTY_OP_INVITE, '', PartyResults.ERR_GROUP_FULL) return False if invite: self.invites[player_mgr.guid] = player_mgr player_mgr.group_manager = self player_mgr.has_pending_group_invite = True return True else: if len(self.members ) == 0: # Party just formed, store the group and params. leader_player = WorldSessionStateHandler.find_player_by_guid( self.group.leader_guid) if leader_player: # If online, we set leader group status. RealmDatabaseManager.group_create(self.group) GroupManager.GROUPS[self.group.group_id] = self leader = GroupManager._create_new_member( self.group, leader_player) RealmDatabaseManager.group_add_member(leader) self.members[self.group.leader_guid] = leader leader_player.group_status = WhoPartyStatus.WHO_PARTY_STATUS_IN_PARTY GroupManager._set_leader_flag(leader) else: # Leader went offline after sending the invite. return False new_member = GroupManager._create_new_member( self.group, player_mgr) new_member = RealmDatabaseManager.group_add_member(new_member) self.members[player_mgr.guid] = new_member # Update newly added member group_manager ref, party status and pending invite flag. player_mgr.group_manager = self player_mgr.group_status = WhoPartyStatus.WHO_PARTY_STATUS_IN_PARTY player_mgr.has_pending_group_invite = False query_details_packet = NameQueryHandler.get_query_details( player_mgr.player) self.send_packet_to_members(query_details_packet) if len(self.members) > 1: self.send_update() self.send_party_members_stats() return True
def handle(world_session, socket, reader): if len(reader.data) >= 8: # Avoid handling empty group uninvite guid packet guid = unpack('<Q', reader.data[:8])[0] target_player_mgr = WorldSessionStateHandler.find_player_by_guid(guid) if not target_player_mgr: GroupManager.send_group_operation_result(world_session.player_mgr, PartyOperations.PARTY_OP_LEAVE, '', PartyResults.ERR_BAD_PLAYER_NAME_S) elif world_session.player_mgr.group_manager: world_session.player_mgr.group_manager.un_invite_player(world_session.player_mgr, target_player_mgr) else: GroupManager.send_group_operation_result(world_session.player_mgr, PartyOperations.PARTY_OP_LEAVE, '', PartyResults.ERR_NOT_IN_GROUP) return 0
def send_party_member_stats(self, group_member): player_mgr = WorldSessionStateHandler.find_player_by_guid( group_member.guid) if player_mgr and player_mgr.online: data = pack('<Q2IB6I3f', player_mgr.guid, player_mgr.health, player_mgr.max_health, player_mgr.power_type, player_mgr.get_power_type_value(), player_mgr.get_max_power_value(), player_mgr.level, player_mgr.zone, player_mgr.map_, player_mgr.player.class_, player_mgr.location.x, player_mgr.location.y, player_mgr.location.z) packet = PacketWriter.get_packet(OpCode.SMSG_PARTY_MEMBER_STATS, data) self.send_packet_to_members(packet)