void HandleWhoIs(WhoIsRequest packet) { if (!HasPermission(RBACPermissions.OpcodeWhois)) { SendNotification(CypherStrings.YouNotHavePermission); return; } if (!ObjectManager.NormalizePlayerName(ref packet.CharName)) { SendNotification(CypherStrings.NeedCharacterName); return; } Player player = Global.ObjAccessor.FindPlayerByName(packet.CharName); if (!player) { SendNotification(CypherStrings.PlayerNotExistOrOffline, packet.CharName); return; } PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_ACCOUNT_WHOIS); stmt.AddValue(0, player.GetSession().GetAccountId()); SQLResult result = DB.Login.Query(stmt); if (result.IsEmpty()) { SendNotification(CypherStrings.AccountForPlayerNotFound, packet.CharName); return; } string acc = result.Read <string>(0); if (string.IsNullOrEmpty(acc)) { acc = "Unknown"; } string email = result.Read <string>(1); if (string.IsNullOrEmpty(email)) { email = "Unknown"; } string lastip = result.Read <string>(2); if (string.IsNullOrEmpty(lastip)) { lastip = "Unknown"; } WhoIsResponse response = new WhoIsResponse(); response.AccountName = packet.CharName + "'s " + "account is " + acc + ", e-mail: " + email + ", last ip: " + lastip; SendPacket(response); }
void HandleAddIgnore(AddIgnore packet) { if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } ObjectGuid IgnoreGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(packet.Name); FriendsResult ignoreResult = FriendsResult.IgnoreNotFound; if (IgnoreGuid.IsEmpty()) { if (IgnoreGuid == GetPlayer().GetGUID()) //not add yourself { ignoreResult = FriendsResult.IgnoreSelf; } else if (GetPlayer().GetSocial().HasIgnore(IgnoreGuid)) { ignoreResult = FriendsResult.IgnoreAlready; } else { ignoreResult = FriendsResult.IgnoreAdded; // ignore list full if (!GetPlayer().GetSocial().AddToSocialList(IgnoreGuid, SocialFlag.Ignored)) { ignoreResult = FriendsResult.IgnoreFull; } } } Global.SocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, IgnoreGuid); }
void HandleChannelPlayerCommand(ChannelPlayerCommand packet) { if (packet.Name.Length >= 49) { Log.outDebug(LogFilter.ChatSystem, "{0} {1} ChannelName: {2}, Name: {3}, Name too long.", packet.GetOpcode(), GetPlayerInfo(), packet.ChannelName, packet.Name); return; } if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } Channel channel = ChannelManager.GetChannelForPlayerByNamePart(packet.ChannelName, GetPlayer()); if (channel == null) { return; } switch (packet.GetOpcode()) { case ClientOpcodes.ChatChannelBan: channel.Ban(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelInvite: channel.Invite(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelKick: channel.Kick(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelModerator: channel.SetModerator(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelSetOwner: channel.SetOwner(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelSilenceAll: channel.SilenceAll(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelUnban: channel.UnBan(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelUnmoderator: channel.UnsetModerator(GetPlayer(), packet.Name); break; case ClientOpcodes.ChatChannelUnsilenceAll: channel.UnsilenceAll(GetPlayer(), packet.Name); break; } }
void HandleAddFriend(AddFriend packet) { if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } FriendsResult friendResult = FriendsResult.NotFound; ObjectGuid friendGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(packet.Name); if (!friendGuid.IsEmpty()) { CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(friendGuid); if (characterInfo != null) { Team team = Player.TeamForRace(characterInfo.RaceId); uint friendAccountId = characterInfo.AccountId; if (HasPermission(RBACPermissions.AllowGmFriend) || Global.AccountMgr.IsPlayerAccount(Global.AccountMgr.GetSecurity(friendAccountId, (int)Global.WorldMgr.GetRealm().Id.Realm))) { if (friendGuid == GetPlayer().GetGUID()) { friendResult = FriendsResult.Self; } else if (GetPlayer().GetTeam() != team && !HasPermission(RBACPermissions.TwoSideAddFriend)) { friendResult = FriendsResult.Enemy; } else if (GetPlayer().GetSocial().HasFriend(friendGuid)) { friendResult = FriendsResult.Already; } else { Player playerFriend = Global.ObjAccessor.FindPlayer(friendGuid); if (playerFriend && playerFriend.IsVisibleGloballyFor(GetPlayer())) { friendResult = FriendsResult.AddedOnline; } else { friendResult = FriendsResult.AddedOffline; } if (GetPlayer().GetSocial().AddToSocialList(friendGuid, SocialFlag.Friend)) { GetPlayer().GetSocial().SetFriendNote(friendGuid, packet.Notes); } else { friendResult = FriendsResult.ListFull; } } } } } Global.SocialMgr.SendFriendStatus(GetPlayer(), friendResult, friendGuid); }
void HandleAddIgnore(AddIgnore packet) { if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_GUID_BY_NAME); stmt.AddValue(0, packet.Name); _queryProcessor.AddQuery(DB.Characters.AsyncQuery(stmt).WithCallback(HandleAddIgnoreCallBack)); }
void HandleGuildInviteByName(GuildInviteByName packet) { if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } Guild guild = GetPlayer().GetGuild(); if (guild) { guild.HandleInviteMember(this, packet.Name); } }
void HandleAddIgnore(AddIgnore packet) { if (!ObjectManager.NormalizePlayerName(ref packet.Name)) { return; } ObjectGuid ignoreGuid; FriendsResult ignoreResult = FriendsResult.IgnoreNotFound; CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByName(packet.Name); if (characterInfo != null) { ignoreGuid = characterInfo.Guid; ObjectGuid ignoreAccountGuid = ObjectGuid.Create(HighGuid.WowAccount, characterInfo.AccountId); if (ignoreGuid == GetPlayer().GetGUID()) //not add yourself { ignoreResult = FriendsResult.IgnoreSelf; } else if (GetPlayer().GetSocial().HasIgnore(ignoreGuid, ignoreAccountGuid)) { ignoreResult = FriendsResult.IgnoreAlready; } else { ignoreResult = FriendsResult.IgnoreAdded; // ignore list full if (!GetPlayer().GetSocial().AddToSocialList(ignoreGuid, ignoreAccountGuid, SocialFlag.Ignored)) { ignoreResult = FriendsResult.IgnoreFull; } } } Global.SocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, ObjectGuid.Empty); }
void HandleCalendarInvite(CalendarInvitePkt calendarInvite) { ObjectGuid playerGuid = GetPlayer().GetGUID(); ObjectGuid inviteeGuid = ObjectGuid.Empty; Team inviteeTeam = 0; ulong inviteeGuildId = 0; if (!ObjectManager.NormalizePlayerName(ref calendarInvite.Name)) { return; } Player player = Global.ObjAccessor.FindPlayerByName(calendarInvite.Name); if (player) { // Invitee is online inviteeGuid = player.GetGUID(); inviteeTeam = player.GetTeam(); inviteeGuildId = player.GetGuildId(); } else { // Invitee offline, get data from database ObjectGuid guid = Global.CharacterCacheStorage.GetCharacterGuidByName(calendarInvite.Name); if (!guid.IsEmpty()) { CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(guid); if (characterInfo != null) { inviteeGuid = guid; inviteeTeam = Player.TeamForRace(characterInfo.RaceId); inviteeGuildId = characterInfo.GuildId; } } } if (inviteeGuid.IsEmpty()) { Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.PlayerNotFound); return; } if (GetPlayer().GetTeam() != inviteeTeam && !WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionCalendar)) { Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.NotAllied); return; } SQLResult result1 = DB.Characters.Query("SELECT flags FROM character_social WHERE guid = {0} AND friend = {1}", inviteeGuid, playerGuid); if (!result1.IsEmpty()) { if (Convert.ToBoolean(result1.Read <byte>(0) & (byte)SocialFlag.Ignored)) { Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.IgnoringYouS, calendarInvite.Name); return; } } if (!calendarInvite.Creating) { CalendarEvent calendarEvent = Global.CalendarMgr.GetEvent(calendarInvite.EventID); if (calendarEvent != null) { if (calendarEvent.IsGuildEvent() && calendarEvent.GuildId == inviteeGuildId) { // we can't invite guild members to guild events Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.NoGuildInvites); return; } CalendarInvite invite = new(Global.CalendarMgr.GetFreeInviteId(), calendarInvite.EventID, inviteeGuid, playerGuid, SharedConst.CalendarDefaultResponseTime, CalendarInviteStatus.Invited, CalendarModerationRank.Player, ""); Global.CalendarMgr.AddInvite(calendarEvent, invite); } else { Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.EventInvalid); } } else { if (calendarInvite.IsSignUp && inviteeGuildId == GetPlayer().GetGuildId()) { Global.CalendarMgr.SendCalendarCommandResult(playerGuid, CalendarError.NoGuildInvites); return; } CalendarInvite invite = new(calendarInvite.EventID, 0, inviteeGuid, playerGuid, SharedConst.CalendarDefaultResponseTime, CalendarInviteStatus.Invited, CalendarModerationRank.Player, ""); Global.CalendarMgr.SendCalendarEventInvite(invite); } }
void HandleChatAddon(ChatMsg type, string prefix, string text, bool isLogged, string target = "") { Player sender = GetPlayer(); if (string.IsNullOrEmpty(prefix) || prefix.Length > 16) { return; } // Disabled addon channel? if (!WorldConfig.GetBoolValue(WorldCfg.AddonChannel)) { return; } switch (type) { case ChatMsg.Guild: case ChatMsg.Officer: if (sender.GetGuildId() != 0) { Guild guild = Global.GuildMgr.GetGuildById(sender.GetGuildId()); if (guild) { guild.BroadcastAddonToGuild(this, type == ChatMsg.Officer, text, prefix, isLogged); } } break; case ChatMsg.Whisper: // @todo implement cross realm whispers (someday) ExtendedPlayerName extName = ObjectManager.ExtractExtendedPlayerName(target); if (!ObjectManager.NormalizePlayerName(ref extName.Name)) { break; } Player receiver = Global.ObjAccessor.FindPlayerByName(extName.Name); if (!receiver) { break; } sender.WhisperAddon(text, prefix, isLogged, receiver); break; // Messages sent to "RAID" while in a party will get delivered to "PARTY" case ChatMsg.Party: case ChatMsg.Raid: case ChatMsg.InstanceChat: { Group group = null; int subGroup = -1; if (type != ChatMsg.InstanceChat) { group = sender.GetOriginalGroup(); } if (!group) { group = sender.GetGroup(); if (!group) { break; } if (type == ChatMsg.Party) { subGroup = sender.GetSubGroup(); } } ChatPkt data = new ChatPkt(); data.Initialize(type, isLogged ? Language.AddonLogged : Language.Addon, sender, null, text, 0, "", LocaleConstant.enUS, prefix); group.BroadcastAddonMessagePacket(data, prefix, true, subGroup, sender.GetGUID()); break; } case ChatMsg.Channel: Channel chn = ChannelManager.GetChannelForPlayerByNamePart(target, sender); if (chn != null) { chn.AddonSay(sender.GetGUID(), prefix, text, isLogged); } break; default: Log.outError(LogFilter.Server, "HandleAddonMessagechat: unknown addon message type {0}", type); break; } }
void HandleChat(ChatMsg type, Language lang, string msg, string target = "") { Player sender = GetPlayer(); if (lang == Language.Universal && type != ChatMsg.Emote) { Log.outError(LogFilter.Network, "CMSG_MESSAGECHAT: Possible hacking-attempt: {0} tried to send a message in universal language", GetPlayerInfo()); SendNotification(CypherStrings.UnknownLanguage); return; } // prevent talking at unknown language (cheating) LanguageDesc langDesc = ObjectManager.GetLanguageDescByID(lang); if (langDesc == null) { SendNotification(CypherStrings.UnknownLanguage); return; } if (langDesc.skill_id != 0 && !sender.HasSkill((SkillType)langDesc.skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) var langAuras = sender.GetAuraEffectsByType(AuraType.ComprehendLanguage); bool foundAura = false; foreach (var eff in langAuras) { if (eff.GetMiscValue() == (int)lang) { foundAura = true; break; } } if (!foundAura) { SendNotification(CypherStrings.NotLearnedLanguage); return; } } // send in universal language if player in .gm on mode (ignore spell effects) if (sender.IsGameMaster()) { lang = Language.Universal; } else { // send in universal language in two side iteration allowed mode if (HasPermission(RBACPermissions.TwoSideInteractionChat)) { lang = Language.Universal; } else { switch (type) { case ChatMsg.Party: case ChatMsg.Raid: case ChatMsg.RaidWarning: // allow two side chat at group channel if two side group allowed if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionGroup)) { lang = Language.Universal; } break; case ChatMsg.Guild: case ChatMsg.Officer: // allow two side chat at guild channel if two side guild allowed if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionGuild)) { lang = Language.Universal; } break; } } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) var ModLangAuras = sender.GetAuraEffectsByType(AuraType.ModLanguage); if (!ModLangAuras.Empty()) { lang = (Language)ModLangAuras.FirstOrDefault().GetMiscValue(); } } if (!CanSpeak()) { string timeStr = Time.secsToTimeString((ulong)(m_muteTime - Time.UnixTime)); SendNotification(CypherStrings.WaitBeforeSpeaking, timeStr); return; } if (sender.HasAura(1852) && type != ChatMsg.Whisper) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.GmSilence), sender.GetName()); return; } if (string.IsNullOrEmpty(msg)) { return; } if (new CommandHandler(this).ParseCommand(msg)) { return; } switch (type) { case ChatMsg.Say: // Prevent cheating if (!sender.IsAlive()) { return; } if (sender.GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatSayLevelReq)) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.SayReq), WorldConfig.GetIntValue(WorldCfg.ChatSayLevelReq)); return; } sender.Say(msg, lang); break; case ChatMsg.Emote: // Prevent cheating if (!sender.IsAlive()) { return; } if (sender.GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatEmoteLevelReq)) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.SayReq), WorldConfig.GetIntValue(WorldCfg.ChatEmoteLevelReq)); return; } sender.TextEmote(msg); break; case ChatMsg.Yell: // Prevent cheating if (!sender.IsAlive()) { return; } if (sender.GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatYellLevelReq)) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.SayReq), WorldConfig.GetIntValue(WorldCfg.ChatYellLevelReq)); return; } sender.Yell(msg, lang); break; case ChatMsg.Whisper: // @todo implement cross realm whispers (someday) ExtendedPlayerName extName = ObjectManager.ExtractExtendedPlayerName(target); if (!ObjectManager.NormalizePlayerName(ref extName.Name)) { SendChatPlayerNotfoundNotice(target); break; } Player receiver = Global.ObjAccessor.FindPlayerByName(extName.Name); if (!receiver || (lang != Language.Addon && !receiver.IsAcceptWhispers() && receiver.GetSession().HasPermission(RBACPermissions.CanFilterWhispers) && !receiver.IsInWhisperWhiteList(sender.GetGUID()))) { SendChatPlayerNotfoundNotice(target); return; } if (!sender.IsGameMaster() && sender.GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatWhisperLevelReq) && !receiver.IsInWhisperWhiteList(sender.GetGUID())) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.WhisperReq), WorldConfig.GetIntValue(WorldCfg.ChatWhisperLevelReq)); return; } if (GetPlayer().GetTeam() != receiver.GetTeam() && !HasPermission(RBACPermissions.TwoSideInteractionChat) && !receiver.IsInWhisperWhiteList(sender.GetGUID())) { SendChatPlayerNotfoundNotice(target); return; } if (GetPlayer().HasAura(1852) && !receiver.IsGameMaster()) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.GmSilence), GetPlayer().GetName()); return; } if (receiver.GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatWhisperLevelReq) || (HasPermission(RBACPermissions.CanFilterWhispers) && !sender.IsAcceptWhispers() && !sender.IsInWhisperWhiteList(receiver.GetGUID()))) { sender.AddWhisperWhiteList(receiver.GetGUID()); } GetPlayer().Whisper(msg, lang, receiver); break; case ChatMsg.Party: { // if player is in Battleground, he cannot say to Battlegroundmembers by /p Group group = GetPlayer().GetOriginalGroup(); if (!group) { group = GetPlayer().GetGroup(); if (!group || group.IsBGGroup()) { return; } } if (group.IsLeader(GetPlayer().GetGUID())) { type = ChatMsg.PartyLeader; } Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, group); ChatPkt data = new ChatPkt(); data.Initialize(type, lang, sender, null, msg); group.BroadcastPacket(data, false, group.GetMemberGroup(GetPlayer().GetGUID())); } break; case ChatMsg.Guild: if (GetPlayer().GetGuildId() != 0) { Guild guild = Global.GuildMgr.GetGuildById(GetPlayer().GetGuildId()); if (guild) { Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, guild); guild.BroadcastToGuild(this, false, msg, lang == Language.Addon ? Language.Addon : Language.Universal); } } break; case ChatMsg.Officer: if (GetPlayer().GetGuildId() != 0) { Guild guild = Global.GuildMgr.GetGuildById(GetPlayer().GetGuildId()); if (guild) { Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, guild); guild.BroadcastToGuild(this, true, msg, lang == Language.Addon ? Language.Addon : Language.Universal); } } break; case ChatMsg.Raid: { Group group = GetPlayer().GetGroup(); if (!group || !group.IsRaidGroup() || group.IsBGGroup()) { return; } if (group.IsLeader(GetPlayer().GetGUID())) { type = ChatMsg.RaidLeader; } Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, group); ChatPkt data = new ChatPkt(); data.Initialize(type, lang, sender, null, msg); group.BroadcastPacket(data, false); } break; case ChatMsg.RaidWarning: { Group group = GetPlayer().GetGroup(); if (!group || !(group.IsRaidGroup() || WorldConfig.GetBoolValue(WorldCfg.ChatPartyRaidWarnings)) || !(group.IsLeader(GetPlayer().GetGUID()) || group.IsAssistant(GetPlayer().GetGUID())) || group.IsBGGroup()) { return; } Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, group); ChatPkt data = new ChatPkt(); //in Battleground, raid warning is sent only to players in Battleground - code is ok data.Initialize(ChatMsg.RaidWarning, lang, sender, null, msg); group.BroadcastPacket(data, false); } break; case ChatMsg.Channel: if (!HasPermission(RBACPermissions.SkipCheckChatChannelReq)) { if (GetPlayer().GetLevel() < WorldConfig.GetIntValue(WorldCfg.ChatChannelLevelReq)) { SendNotification(Global.ObjectMgr.GetCypherString(CypherStrings.ChannelReq), WorldConfig.GetIntValue(WorldCfg.ChatChannelLevelReq)); return; } } Channel chn = ChannelManager.GetChannelForPlayerByNamePart(target, sender); if (chn != null) { Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, chn); chn.Say(GetPlayer().GetGUID(), msg, lang); } break; case ChatMsg.InstanceChat: { Group group = GetPlayer().GetGroup(); if (!group) { return; } if (group.IsLeader(GetPlayer().GetGUID())) { type = ChatMsg.InstanceChatLeader; } Global.ScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, group); ChatPkt packet = new ChatPkt(); packet.Initialize(type, lang, sender, null, msg); group.BroadcastPacket(packet, false); break; } default: Log.outError(LogFilter.ChatSystem, "CHAT: unknown message type {0}, lang: {1}", type, lang); break; } }
void HandleSendMail(SendMail packet) { if (packet.Info.Attachments.Count > SharedConst.MaxMailItems) // client limit { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.TooManyAttachments); return; } if (!CanOpenMailBox(packet.Info.Mailbox)) { return; } if (string.IsNullOrEmpty(packet.Info.Target)) { return; } Player player = GetPlayer(); if (player.getLevel() < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailSenderReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } ObjectGuid receiverGuid = ObjectGuid.Empty; if (ObjectManager.NormalizePlayerName(ref packet.Info.Target)) { receiverGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(packet.Info.Target); } if (receiverGuid.IsEmpty()) { Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} (GUID: not existed!) with subject {2}" + "and body {3} includes {4} items, {5} copper and {6} COD copper with StationeryID = {7}", GetPlayerInfo(), packet.Info.Target, packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientNotFound); return; } if (packet.Info.SendMoney < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative money value (SendMoney: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.SendMoney); return; } if (packet.Info.Cod < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative COD value (Cod: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Cod); return; } Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} ({2}) with subject {3} and body {4}" + "includes {5} items, {6} copper and {7} COD copper with StationeryID = {8}", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); if (player.GetGUID() == receiverGuid) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CannotSendToSelf); return; } uint cost = (uint)(!packet.Info.Attachments.Empty() ? 30 * packet.Info.Attachments.Count : 30); // price hardcoded in client long reqmoney = cost + packet.Info.SendMoney; // Check for overflow if (reqmoney < packet.Info.SendMoney) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } if (!player.HasEnoughMoney(reqmoney) && !player.IsGameMaster()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } Player receiver = Global.ObjAccessor.FindPlayer(receiverGuid); Team receiverTeam = 0; byte mailsCount = 0; //do not allow to send to one player more than 100 mails byte receiverLevel = 0; uint receiverAccountId = 0; uint receiverBnetAccountId = 0; if (receiver) { receiverTeam = receiver.GetTeam(); mailsCount = (byte)receiver.GetMails().Count; receiverLevel = (byte)receiver.getLevel(); receiverAccountId = receiver.GetSession().GetAccountId(); receiverBnetAccountId = receiver.GetSession().GetBattlenetAccountId(); } else { CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(receiverGuid); if (characterInfo != null) { receiverTeam = Player.TeamForRace(characterInfo.RaceId); receiverLevel = characterInfo.Level; receiverAccountId = characterInfo.AccountId; } PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAIL_COUNT); stmt.AddValue(0, receiverGuid.GetCounter()); SQLResult result = DB.Characters.Query(stmt); if (!result.IsEmpty()) { mailsCount = (byte)result.Read <ulong>(0); } receiverBnetAccountId = Global.BNetAccountMgr.GetIdByGameAccount(receiverAccountId); } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode byte!!! - so max can be 255.. if (mailsCount > 100) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientCapReached); return; } // test the receiver's Faction... or all items are account bound bool accountBound = !packet.Info.Attachments.Empty(); foreach (var att in packet.Info.Attachments) { Item item = player.GetItemByGuid(att.ItemGUID); if (item) { ItemTemplate itemProto = item.GetTemplate(); if (itemProto == null || !itemProto.GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount)) { accountBound = false; break; } } } if (!accountBound && player.GetTeam() != receiverTeam && !HasPermission(RBACPermissions.TwoSideInteractionMail)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotYourTeam); return; } if (receiverLevel < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailReceiverReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } List <Item> items = new List <Item>(); foreach (var att in packet.Info.Attachments) { if (att.ItemGUID.IsEmpty()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } Item item = player.GetItemByGuid(att.ItemGUID); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } if (!item.CanBeTraded(true)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (item.IsBoundAccountWide() && item.IsSoulBound() && player.GetSession().GetAccountId() != receiverAccountId) { if (!item.IsBattlenetAccountBound() || player.GetSession().GetBattlenetAccountId() == 0 || player.GetSession().GetBattlenetAccountId() != receiverBnetAccountId) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.NotSameAccount); return; } } if (item.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || item.m_itemData.Expiration != 0) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (packet.Info.Cod != 0 && item.HasItemFlag(ItemFieldFlags.Wrapped)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CantSendWrappedCod); return; } if (item.IsNotEmptyBag()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.DestroyNonemptyBag); return; } items.Add(item); } player.SendMailResult(0, MailResponseType.Send, MailResponseResult.Ok); player.ModifyMoney(-reqmoney); player.UpdateCriteria(CriteriaTypes.GoldSpentForMail, cost); bool needItemDelay = false; MailDraft draft = new MailDraft(packet.Info.Subject, packet.Info.Body); SQLTransaction trans = new SQLTransaction(); if (!packet.Info.Attachments.Empty() || packet.Info.SendMoney > 0) { bool log = HasPermission(RBACPermissions.LogGmTrade); if (!packet.Info.Attachments.Empty()) { foreach (var item in items) { if (log) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {2}) mail item: {3} (Entry: {4} Count: {5}) to player: {6} ({7}) (Account: {8})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), item.GetTemplate().GetName(), item.GetEntry(), item.GetCount(), packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } item.SetNotRefundable(GetPlayer()); // makes the item no longer refundable player.MoveItemFromInventory(item.GetBagSlot(), item.GetSlot(), true); item.DeleteFromInventoryDB(trans); // deletes item from character's inventory item.SetOwnerGUID(receiverGuid); item.SetState(ItemUpdateState.Changed); item.SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player.GetSession().GetAccountId() != receiverAccountId; } if (log && packet.Info.SendMoney > 0) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {{2}) mail money: {3} to player: {4} ({5}) (Account: {6})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), packet.Info.SendMoney, packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint deliver_delay = needItemDelay ? WorldConfig.GetUIntValue(WorldCfg.MailDeliveryDelay) : 0; // Mail sent between guild members arrives instantly Guild guild = Global.GuildMgr.GetGuildById(player.GetGuildId()); if (guild) { if (guild.IsMember(receiverGuid)) { deliver_delay = 0; } } // don't ask for COD if there are no items if (packet.Info.Attachments.Empty()) { packet.Info.Cod = 0; } // will delete item or place to receiver mail list draft.AddMoney((ulong)packet.Info.SendMoney).AddCOD((uint)packet.Info.Cod).SendMailTo(trans, new MailReceiver(receiver, receiverGuid.GetCounter()), new MailSender(player), string.IsNullOrEmpty(packet.Info.Body) ? MailCheckMask.Copied : MailCheckMask.HasBody, deliver_delay); player.SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); }