def update_item_count(self, item_entry, quantity): req_items = QuestHelpers.generate_req_item_list(self.quest) req_count = QuestHelpers.generate_req_item_count_list(self.quest) req_item_index = req_items.index(item_entry) # Persist new item count. self._update_db_item_count( req_item_index, quantity, req_count[req_item_index]) # Update db memento # Notify the current item count to the player. data = pack('<2I', item_entry, quantity) packet = PacketWriter.get_packet(OpCode.SMSG_QUESTUPDATE_ADD_ITEM, data) self.owner.enqueue_packet(packet) # Check if this makes it complete. if self.can_complete_quest(): self.update_quest_state(QuestState.QUEST_REWARD)
def send_equip_error(self, error, item_1=None, item_2=None, required_level=0): data = pack('<B', error) if error != InventoryError.BAG_OK: if error == InventoryError.BAG_LEVEL_MISMATCH: data += pack( '<I', item_1.item_template.required_level if item_1 else required_level) data += pack('<2QB', item_1.guid if item_1 else self.owner.guid, item_2.guid if item_2 else self.owner.guid, 0) self.owner.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_INVENTORY_CHANGE_FAILURE, data))
def add_new_member(self, player_mgr, is_guild_master=False): rank = GuildRank.GUILDRANK_GUILD_MASTER if is_guild_master else GuildRank.GUILDRANK_INITIATE guild_member = self._create_new_member(player_mgr.guid, rank) player_mgr.guild_manager = self self.members[player_mgr.guid] = guild_member data = pack('<2B', GuildEvents.GUILD_EVENT_JOINED, 1) name_bytes = PacketWriter.string_to_bytes(player_mgr.player.name) data += pack(f'<{len(name_bytes)}s', name_bytes) self.build_update(player_mgr) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) RealmDatabaseManager.character_update(player_mgr.player)
def _gen_item_struct(self, item_entry, count): item_template = WorldDatabaseManager.ItemTemplateHolder.item_template_get_by_entry(item_entry) display_id = 0 if item_template: display_id = item_template.display_id query_data = ItemManager.generate_query_details_data(item_template) self.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_ITEM_QUERY_SINGLE_RESPONSE, query_data)) item_data = pack( '<3I', item_entry, count, display_id ) return item_data
def send_single_item_update(self, world_session, item, is_self): update_packet = UpdatePacketFactory.compress_if_needed( PacketWriter.get_packet( OpCode.SMSG_UPDATE_OBJECT, item.get_update_packet(update_type=UpdateTypes.UPDATE_FULL, is_self=False))) if is_self: world_session.request.sendall(update_packet) world_session.request.sendall(item.query_details()) else: GridManager.send_surrounding(update_packet, world_session.player_mgr, include_self=False) GridManager.send_surrounding(item.query_details(), world_session.player_mgr, include_self=False)
def reward_group_creature_or_go(self, player, creature): surrounding_players = MapManager.get_surrounding_players( player).values() surrounding_members = [ player for player in surrounding_players if player.guid in self.members ] # Party kill log packet, not sure how to display on client but, it is handled. data = pack('<2Q', player.guid, creature.guid) # Player with killing blow and victim guid. kill_log_packet = PacketWriter.get_packet(OpCode.SMSG_PARTYKILLLOG, data) for member in surrounding_members: member.enqueue_packet(kill_log_packet) member.quest_manager.reward_creature_or_go(creature)
def send_online_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( '<BQB3I', FriendResults.FRIEND_ONLINE, self.owner.guid, 1, # Online MapManager.get_parent_zone_id(self.owner.zone, self.owner.map_), self.owner.level, self.owner.player.class_ ) packet = PacketWriter.get_packet(OpCode.SMSG_FRIEND_STATUS, data) player_mgr.session.enqueue_packet(packet) player_mgr.friends_manager.send_friends()
def handle(world_session, socket, reader): if len(reader.data) >= 8: # Avoid handling empty binder activate packet binder_guid = unpack('<Q', reader.data[:8])[0] if binder_guid > 0: world_session.player_mgr.deathbind.creature_binder_guid = binder_guid & ~HighGuid.HIGHGUID_UNIT world_session.player_mgr.deathbind.deathbind_map = world_session.player_mgr.map_ world_session.player_mgr.deathbind.deathbind_zone = world_session.player_mgr.zone world_session.player_mgr.deathbind.deathbind_position_x = world_session.player_mgr.location.x world_session.player_mgr.deathbind.deathbind_position_y = world_session.player_mgr.location.y world_session.player_mgr.deathbind.deathbind_position_z = world_session.player_mgr.location.z RealmDatabaseManager.character_update_deathbind(world_session.player_mgr.deathbind) socket.sendall(world_session.player_mgr.get_deathbind_packet()) data = pack('<Q', binder_guid) socket.sendall(PacketWriter.get_packet(OpCode.SMSG_PLAYERBOUND, data)) return 0
def send_quest_giver_request_items(self, active_quest, quest_giver_id, close_on_cancel): is_complete = active_quest.is_quest_complete(quest_giver_id) quest_title_bytes = PacketWriter.string_to_bytes( active_quest.quest.Title) quest = active_quest.quest if quest.RequestItemsText: dialog_text_bytes = PacketWriter.string_to_bytes( quest.RequestItemsText) else: dialog_text_bytes = PacketWriter.string_to_bytes(quest.Objectives) data = pack( f'<QI{len(quest_title_bytes)}s{len(dialog_text_bytes)}s4I', quest_giver_id, quest.entry, quest_title_bytes, dialog_text_bytes, 0, # Emote delay 0, # Emote id 1 if close_on_cancel else 0, # Close Window after cancel quest.RewOrReqMoney if quest.RewOrReqMoney >= 0 else -quest.RewOrReqMoney) req_items = QuestHelpers.generate_req_item_list(quest) req_items_count_list = QuestHelpers.generate_req_item_count_list(quest) data += pack('<I', len(req_items)) for index in range(0, 4): if req_items[index] == 0: continue data += self._gen_item_struct(req_items[index], req_items_count_list[index]) data += pack( '<4I', 0x02, 0x03 if is_complete else 0x00, # Completable = flags1 && flags2 && flags3 && flags4 0x04, # flags2 0x08 # flags3 ) packet = PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_REQUEST_ITEMS, data) self.player_mgr.enqueue_packet(packet)
def send_item_receive_message(self, guid, item_entry, bag_slot, looted=False, show_in_chat=True): if bag_slot == InventorySlots.SLOT_INBACKPACK: bag_slot = 0xFF data = pack('<Q2IBI', guid, not looted, show_in_chat, bag_slot, item_entry) packet = PacketWriter.get_packet(OpCode.SMSG_ITEM_PUSH_RESULT, data) if looted and self.owner.group_manager: self.owner.group_manager.send_packet_to_members( packet, source=self.owner, surrounding_only=True) else: self.owner.session.enqueue_packet(packet)
def send_party_member_stats(self, player_mgr): data = pack( '<Q2IB6I', player_mgr.guid, player_mgr.health, player_mgr.max_health, player_mgr.power_type, player_mgr.get_power_type_value(), # Todo Current power value player_mgr.get_power_type_value(), # Todo Max power value player_mgr.level, player_mgr.zone, player_mgr.map_, player_mgr.player.class_, ) packet = PacketWriter.get_packet(OpCode.SMSG_PARTY_MEMBER_STATS, data) self.send_packet_to_members(packet)
def send_initialize_factions(self, set_visible=True): data = pack('<I', CLIENT_MAX) for x in range(0, CLIENT_MAX): if x in self.reputations: faction = DbcDatabaseManager.FactionHolder.faction_get_by_index( x) data += pack( '<Bi', self.reputations[x].flags, self.reputations[x].standing - faction.ReputationBase_1) else: data += pack('<Bi', 0, 0) packet = PacketWriter.get_packet(OpCode.SMSG_INITIALIZE_FACTIONS, data) self.player_mgr.session.enqueue_packet(packet) if set_visible: for reputation in self.reputations.values(): self.send_set_faction_visible(reputation)
def leave(self, player_guid): member = self.members[player_guid] data = pack('<2B', GuildEvents.GUILD_EVENT_LEFT, 1) leaver_name_bytes = PacketWriter.string_to_bytes(member.character.name) data += pack(f'<{len(leaver_name_bytes)}s', leaver_name_bytes) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) RealmDatabaseManager.guild_remove_member(member) self.members.pop(player_guid) player_mgr = WorldSessionStateHandler.find_player_by_guid(player_guid) if player_mgr: self.build_update(player_mgr, unset=True) player_mgr.guild_manager = None player_mgr.set_dirty()
def use(self, player): if self.gobject_template.type == GameObjectTypes.TYPE_DOOR or \ self.gobject_template.type == GameObjectTypes.TYPE_BUTTON: # TODO: Check locks for doors if self.state == GameObjectStates.GO_STATE_READY: self.state = GameObjectStates.GO_STATE_ACTIVE # TODO: Trigger sripts / events on cooldown restart self.send_update_surrounding() elif self.gobject_template.type == GameObjectTypes.TYPE_CAMERA: cinematic_id = self.gobject_template.data1 if DbcDatabaseManager.cinematic_sequences_get_by_id(cinematic_id): data = pack('<I', cinematic_id) player.session.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_TRIGGER_CINEMATIC, data)) elif self.gobject_template.type == GameObjectTypes.TYPE_CHAIR: slots = self.gobject_template.data0 height = self.gobject_template.data1 lowest_distance = 90.0 x_lowest = self.location.x y_lowest = self.location.y if slots > 0: orthogonal_orientation = self.location.o + pi * 0.5 for x in range(0, slots): relative_distance = (self.current_scale * x) - (self.current_scale * (slots - 1) / 2.0) x_i = self.location.x + relative_distance * cos( orthogonal_orientation) y_i = self.location.y + relative_distance * sin( orthogonal_orientation) player_slot_distance = player.location.distance( Vector(x_i, y_i, player.location.z)) if player_slot_distance <= lowest_distance: lowest_distance = player_slot_distance x_lowest = x_i y_lowest = y_i player.teleport( player.map_, Vector(x_lowest, y_lowest, self.location.z, self.location.o)) player.set_stand_state(StandState.UNIT_SITTINGCHAIRLOW.value + height)
def _get_message_packet(guid, chat_flags, message, chat_type, lang, channel=None): message_bytes = PacketWriter.string_to_bytes(message) data = pack('<BI', chat_type, lang) if not channel: data += pack('<Q', guid) else: channel_bytes = PacketWriter.string_to_bytes(channel) data += pack(f'<{len(channel_bytes)}sQ', channel_bytes, guid) data += pack(f'<{len(message_bytes)}sB', message_bytes, chat_flags) return PacketWriter.get_packet(OpCode.SMSG_MESSAGECHAT, data)
def handle(world_session, socket, reader): if len(reader.data) >= 16: # Avoid handling empty activate taxi packet. guid, start_node, dest_node = unpack('<Q2I', reader.data[:16]) if guid <= 0: return result = ActivateTaxiReplies.ERR_TAXIOK if world_session.player_mgr.in_combat: result = ActivateTaxiReplies.ERR_TAXIPLAYERBUSY elif world_session.player_mgr.mount_display_id > 0: result = ActivateTaxiReplies.ERR_TAXIPLAYERALREADYMOUNTED taxi_path = DbcDatabaseManager.taxi_path_get(start_node, dest_node) if not taxi_path: result = ActivateTaxiReplies.ERR_TAXINOSUCHPATH if world_session.player_mgr.coinage < taxi_path.Cost: result = ActivateTaxiReplies.ERR_TAXINOTENOUGHMONEY data = pack('<I', result) world_session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_ACTIVATETAXIREPLY, data)) if result == ActivateTaxiReplies.ERR_TAXIOK: world_session.player_mgr.mod_money(-taxi_path.Cost) waypoints = [] taxi_path_nodes = DbcDatabaseManager.TaxiPathNodesHolder.taxi_nodes_get_by_path_id(taxi_path.ID) for taxi_path_node in taxi_path_nodes: waypoints.append(Vector(taxi_path_node.LocX, taxi_path_node.LocY, taxi_path_node.LocZ)) world_session.player_mgr.unit_flags |= UnitFlags.UNIT_FLAG_FROZEN | UnitFlags.UNIT_FLAG_TAXI_FLIGHT world_session.player_mgr.set_uint32(UnitFields.UNIT_FIELD_FLAGS, world_session.player_mgr.unit_flags) dest_taxi_node = DbcDatabaseManager.TaxiNodesHolder.taxi_nodes_get_by_map_and_id( world_session.player_mgr.map_, dest_node) world_session.player_mgr.pending_taxi_destination = Vector(dest_taxi_node.X, dest_taxi_node.Y, dest_taxi_node.Z) world_session.player_mgr.mount(GRYPHON_DISPLAY_ID) world_session.player_mgr.set_dirty() world_session.player_mgr.movement_manager.send_move_to(waypoints, config.Unit.Player.Defaults.flight_speed, SplineFlags.SPLINEFLAG_FLYING) return 0
def update_creature_go_count(self, creature, value): creature_go_index = QuestHelpers.generate_req_creature_or_go_list( self.quest).index(creature.entry) required = QuestHelpers.generate_req_creature_or_go_count_list( self.quest)[creature_go_index] current = self._get_db_mob_or_go_count(creature_go_index) # Current < Required is already validated on requires_creature_or_go(). self._update_db_creature_go_count(creature_go_index, 1) # Update db memento # Notify the current objective count to the player. data = pack('<4IQ', self.db_state.quest, creature.entry, current + value, required, creature.guid) packet = PacketWriter.get_packet(OpCode.SMSG_QUESTUPDATE_ADD_KILL, data) self.owner.enqueue_packet(packet) # Check if this makes it complete. if self.can_complete_quest(): self.update_quest_state(QuestState.QUEST_REWARD)
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, # Online MapManager.get_parent_zone_id(player_mgr.zone, player_mgr.map_), player_mgr.level, player_mgr.player.class_ ) self.owner.session.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_FRIEND_STATUS, data)) self.send_friends()
def send_quest_giver_quest_list(self, message, quest_giver_guid, quest): message_bytes = PacketWriter.string_to_bytes(message) data = pack( f'<Q{len(message_bytes)}s2iB', quest_giver_guid, message_bytes, 0, # TODO: delay 0, # TODO: emoteID len(quest)) for entry in quest: quest_title = PacketWriter.string_to_bytes( quest[entry].quest.Title) data += pack(f'<3I{len(quest_title)}s', entry, quest[entry].state, quest[entry].quest.QuestLevel, quest_title) self.player_mgr.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_QUEST_LIST, data))
def turn_in_petition(player_mgr, petition_owner, petition): if petition and petition_owner: if petition_owner != player_mgr.guid: PetitionManager.send_petition_sign_result(player_mgr, PetitionError.PETITION_CHARTER_CREATOR) elif len(petition.characters) < 9: PetitionManager.send_petition_sign_result(player_mgr, PetitionError.PETITION_NOT_ENOUGH_SIGNATURES) elif player_mgr.guild_manager: PetitionManager.send_petition_sign_result(player_mgr, PetitionError.PETITION_ALREADY_IN_GUILD) else: # If not able to create a guild, GuildManager will report the error. if GuildManager.create_guild(player_mgr, petition.name, petition=petition): data = pack('<I', PetitionError.PETITION_SUCCESS) packet = PacketWriter.get_packet(OpCode.SMSG_TURN_IN_PETITION_RESULTS, data) player_mgr.session.enqueue_packet(packet) player_mgr.inventory.remove_item(PetitionManager.CHARTER_ENTRY, 1) RealmDatabaseManager.guild_petition_destroy(petition) else: PetitionManager.send_petition_sign_result(player_mgr, PetitionError.PETITION_UNKNOWN_ERROR)
def send_quest_giver_quest_list(self, message, quest_giver_guid, quests): message_bytes = PacketWriter.string_to_bytes(message) data = pack( '<Q%us2iB' % len(message_bytes), quest_giver_guid, message_bytes, 0, # TODO: Gossip menu count 0, # TODO: Gossip menu items len(quests)) for entry in quests: quest_title = PacketWriter.string_to_bytes( quests[entry].quest.Title) data += pack('<3I%us' % len(quest_title), entry, quests[entry].status, quests[entry].quest.QuestLevel, quest_title) self.player_mgr.session.request.sendall( PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_QUEST_LIST, data))
def disband(self): data = pack('<2B', GuildEvents.GUILD_EVENT_DISBANDED, 1) leaver_name_bytes = PacketWriter.string_to_bytes( self.guild_master.character.name) data += pack(f'<{len(leaver_name_bytes)}s', leaver_name_bytes) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) for member in self.members.values(): player_mgr = WorldSessionStateHandler.find_player_by_guid( member.guid) if player_mgr: self.build_update(player_mgr, unset=True) player_mgr.guild_manager = None GuildManager.GUILDS.pop(self.guild.name) self.members.clear() RealmDatabaseManager.guild_destroy(self.guild)
def leave(self, player_mgr): data = pack('<2B', GuildEvents.GUILD_EVENT_LEFT, 1) leaver_name_bytes = PacketWriter.string_to_bytes( player_mgr.player.name) data += pack( '<%us' % len(leaver_name_bytes), leaver_name_bytes, ) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) self.members.pop(player_mgr.guid) self.ranks.pop(player_mgr.guid) self.build_update(player_mgr, unset=True) player_mgr.guild_manager = None player_mgr.set_dirty()
def leave_party(self, player_mgr, force_disband=False, is_kicked=False): disband = player_mgr == self.party_leader or len(self.members) == 2 or force_disband for member in self.members.values(): if disband or member == player_mgr: GroupManager.send_group_operation_result(member, PartyOperations.PARTY_OP_LEAVE, member.player.name, PartyResults.ERR_PARTY_RESULT_OK) member.group_manager = None member.set_group_leader(False) member.group_status = WhoPartyStatus.WHO_PARTY_STATUS_NOT_IN_PARTY if is_kicked and member == player_mgr: # 'You have been removed from the group.' packet = PacketWriter.get_packet(OpCode.SMSG_GROUP_UNINVITE) player_mgr.session.request.sendall(packet) if disband: self.members.clear() elif player_mgr.guid in self.members: self.members.pop(player_mgr.guid) self.send_update()
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 add_item(self, entry, count=1): item_template = WorldDatabaseManager.item_template_get_by_entry(entry) if item_template: if not self.can_store_item(item_template, count): self.send_equip_error( InventoryError.EQUIP_ERR_CANT_CARRY_MORE_OF_THIS) if count <= item_template.stackable: for slot, container in self.containers.items(): if not container.is_full(): item_mgr = container.add_item(item_template) if item_mgr: self.owner.session.request.sendall( PacketWriter.get_packet( OpCode.SMSG_UPDATE_OBJECT, self.owner.get_update_packet( update_type=UpdateTypes.UPDATE_FULL, is_self=True))) return item_mgr return None
def query_details(self): name_bytes = PacketWriter.string_to_bytes(self.gobject_template.name) data = pack( f'<3I{len(name_bytes)}ssss10I', self.gobject_template.entry, self.gobject_template.type, self.current_display_id, name_bytes, b'\x00', b'\x00', b'\x00', self.gobject_template.data0, self.gobject_template.data1, self.gobject_template.data2, self.gobject_template.data3, self.gobject_template.data4, self.gobject_template.data5, self.gobject_template.data6, self.gobject_template.data7, self.gobject_template.data8, self.gobject_template.data9 ) return PacketWriter.get_packet(OpCode.SMSG_GAMEOBJECT_QUERY_RESPONSE, data)
def add_new_member(self, player_mgr, is_guild_master=False): self.members[player_mgr.guid] = player_mgr player_mgr.guild_manager = self if is_guild_master: self.set_guild_master(player_mgr) else: self.ranks[player_mgr.guid] = GuildRank.GUILDRANK_INITIATE data = pack('<2B', GuildEvents.GUILD_EVENT_JOINED, 1) name_bytes = PacketWriter.string_to_bytes(player_mgr.player.name) data += pack( '<%us' % len(name_bytes), name_bytes, ) packet = PacketWriter.get_packet(OpCode.SMSG_GUILD_EVENT, data) self.send_message_to_guild(packet, GuildChatMessageTypes.G_MSGTYPE_ALL) self.build_update(player_mgr) player_mgr.set_dirty()
def send_attack_state_update(self, damage_info): data = pack('<I2QIBIf7I', damage_info.hit_info, damage_info.attacker.guid, damage_info.target.guid, damage_info.total_damage, 1, # Sub damage count damage_info.damage_school_mask, damage_info.total_damage, damage_info.damage, damage_info.absorb, damage_info.target_state, damage_info.resist, 0, 0, damage_info.blocked_amount) GridManager.send_surrounding(PacketWriter.get_packet(OpCode.SMSG_ATTACKERSTATEUPDATE, data), self, include_self=self.get_type() == ObjectTypes.TYPE_PLAYER) # Damage effects self.deal_damage(damage_info.target, damage_info.total_damage)
def list_channel(channel, sender): if not ChannelManager._exist(channel, sender): packet = ChannelManager.build_notify_packet(channel, ChannelNotifications.NOT_MEMBER) ChannelManager.send_to_player(sender, packet) else: len_members = len(ChannelManager.CHANNELS[sender.team][channel].members) name_bytes = PacketWriter.string_to_bytes(ChannelManager.CHANNELS[sender.team][channel].name) data = pack(f'<{len(name_bytes)}sBI', name_bytes, 0x3, len_members) # TODO '0x3' Unknown flags. for member in ChannelManager._get_members(channel, sender): data += pack('<Q', member.guid) mode = 0 if ChannelManager._is_muted(channel, member): mode |= ChannelMemberFlags.VOICE if ChannelManager._is_moderator(channel, member) or ChannelManager._is_owner(channel, member): mode |= ChannelMemberFlags.MODERATOR data += pack('<B', mode) packet = PacketWriter.get_packet(OpCode.SMSG_CHANNEL_LIST, data) ChannelManager.send_to_player(sender, packet)