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 HandlePetitionBuy(PetitionBuy packet) { // prevent cheating Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Unit, NPCFlags.Petitioner, NPCFlags2.None); if (!creature) { Log.outDebug(LogFilter.Network, "WORLD: HandlePetitionBuyOpcode - {0} not found or you can't interact with him.", packet.Unit.ToString()); return; } // remove fake death if (GetPlayer().HasUnitState(UnitState.Died)) { GetPlayer().RemoveAurasByType(AuraType.FeignDeath); } uint charterItemID = GuildConst.CharterItemId; int cost = WorldConfig.GetIntValue(WorldCfg.CharterCostGuild); // do not let if already in guild. if (GetPlayer().GetGuildId() != 0) { return; } if (Global.GuildMgr.GetGuildByName(packet.Title)) { Guild.SendCommandResult(this, GuildCommandType.CreateGuild, GuildCommandError.NameExists_S, packet.Title); return; } if (Global.ObjectMgr.IsReservedName(packet.Title) || !ObjectManager.IsValidCharterName(packet.Title)) { Guild.SendCommandResult(this, GuildCommandType.CreateGuild, GuildCommandError.NameInvalid, packet.Title); return; } ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(charterItemID); if (pProto == null) { GetPlayer().SendBuyError(BuyResult.CantFindItem, null, charterItemID); return; } if (!GetPlayer().HasEnoughMoney(cost)) { //player hasn't got enough money GetPlayer().SendBuyError(BuyResult.NotEnoughtMoney, creature, charterItemID); return; } List <ItemPosCount> dest = new List <ItemPosCount>(); InventoryResult msg = GetPlayer().CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, charterItemID, pProto.GetBuyCount()); if (msg != InventoryResult.Ok) { GetPlayer().SendEquipError(msg, null, null, charterItemID); return; } GetPlayer().ModifyMoney(-cost); Item charter = GetPlayer().StoreNewItem(dest, charterItemID, true); if (!charter) { return; } charter.SetPetitionId((uint)charter.GetGUID().GetCounter()); charter.SetState(ItemUpdateState.Changed, GetPlayer()); GetPlayer().SendNewItem(charter, 1, true, false); // a petition is invalid, if both the owner and the type matches // we checked above, if this player is in an arenateam, so this must be // datacorruption PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_PETITION_BY_OWNER); stmt.AddValue(0, GetPlayer().GetGUID().GetCounter()); SQLResult result = DB.Characters.Query(stmt); StringBuilder ssInvalidPetitionGUIDs = new StringBuilder(); if (!result.IsEmpty()) { do { ssInvalidPetitionGUIDs.AppendFormat("'{0}', ", result.Read <uint>(0)); } while (result.NextRow()); } // delete petitions with the same guid as this one ssInvalidPetitionGUIDs.AppendFormat("'{0}'", charter.GetGUID().GetCounter()); Log.outDebug(LogFilter.Network, "Invalid petition GUIDs: {0}", ssInvalidPetitionGUIDs.ToString()); SQLTransaction trans = new SQLTransaction(); trans.Append("DELETE FROM petition WHERE petitionguid IN ({0})", ssInvalidPetitionGUIDs.ToString()); trans.Append("DELETE FROM petition_sign WHERE petitionguid IN ({0})", ssInvalidPetitionGUIDs.ToString()); stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_PETITION); stmt.AddValue(0, GetPlayer().GetGUID().GetCounter()); stmt.AddValue(1, charter.GetGUID().GetCounter()); stmt.AddValue(2, packet.Title); trans.Append(stmt); DB.Characters.CommitTransaction(trans); }
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 (!sender.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; } }
public void LoadCreatureTexts() { uint oldMSTime = Time.GetMSTime(); mTextMap.Clear(); // for reload case //all currently used temp texts are NOT reset PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.SEL_CREATURE_TEXT); SQLResult result = DB.World.Query(stmt); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 ceature texts. DB table `creature_texts` is empty."); return; } uint textCount = 0; uint creatureCount = 0; do { CreatureTextEntry temp = new(); temp.creatureId = result.Read <uint>(0); temp.groupId = result.Read <byte>(1); temp.id = result.Read <byte>(2); temp.text = result.Read <string>(3); temp.type = (ChatMsg)result.Read <byte>(4); temp.lang = (Language)result.Read <byte>(5); temp.probability = result.Read <float>(6); temp.emote = (Emote)result.Read <uint>(7); temp.duration = result.Read <uint>(8); temp.sound = result.Read <uint>(9); temp.BroadcastTextId = result.Read <uint>(10); temp.TextRange = (CreatureTextRange)result.Read <byte>(11); if (temp.sound != 0) { if (!CliDB.SoundKitStorage.ContainsKey(temp.sound)) { Log.outError(LogFilter.Sql, "GossipManager: Entry {0}, Group {1} in table `creature_texts` has Sound {2} but sound does not exist.", temp.creatureId, temp.groupId, temp.sound); temp.sound = 0; } } if (ObjectManager.GetLanguageDescByID(temp.lang) == null) { Log.outError(LogFilter.Sql, "GossipManager: Entry {0}, Group {1} in table `creature_texts` using Language {2} but Language does not exist.", temp.creatureId, temp.groupId, temp.lang); temp.lang = Language.Universal; } if (temp.type >= ChatMsg.Max) { Log.outError(LogFilter.Sql, "GossipManager: Entry {0}, Group {1} in table `creature_texts` has Type {2} but this Chat Type does not exist.", temp.creatureId, temp.groupId, temp.type); temp.type = ChatMsg.Say; } if (temp.emote != 0) { if (!CliDB.EmotesStorage.ContainsKey((uint)temp.emote)) { Log.outError(LogFilter.Sql, "GossipManager: Entry {0}, Group {1} in table `creature_texts` has Emote {2} but emote does not exist.", temp.creatureId, temp.groupId, temp.emote); temp.emote = Emote.OneshotNone; } } if (temp.BroadcastTextId != 0) { if (!CliDB.BroadcastTextStorage.ContainsKey(temp.BroadcastTextId)) { Log.outError(LogFilter.Sql, "CreatureTextMgr: Entry {0}, Group {1}, Id {2} in table `creature_texts` has non-existing or incompatible BroadcastTextId {3}.", temp.creatureId, temp.groupId, temp.id, temp.BroadcastTextId); temp.BroadcastTextId = 0; } } if (temp.TextRange > CreatureTextRange.World) { Log.outError(LogFilter.Sql, "CreatureTextMgr: Entry {0}, Group {1}, Id {2} in table `creature_text` has incorrect TextRange {3}.", temp.creatureId, temp.groupId, temp.id, temp.TextRange); temp.TextRange = CreatureTextRange.Normal; } if (!mTextMap.ContainsKey(temp.creatureId)) { mTextMap[temp.creatureId] = new MultiMap <byte, CreatureTextEntry>(); ++creatureCount; } mTextMap[temp.creatureId].Add(temp.groupId, temp); ++textCount; } while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creature texts for {1} creatures in {2} ms", textCount, creatureCount, Time.GetMSTimeDiffToNow(oldMSTime)); }
void HandlePetRename(PetRename packet) { ObjectGuid petguid = packet.RenameData.PetGUID; bool isdeclined = packet.RenameData.HasDeclinedNames; string name = packet.RenameData.NewName; Pet pet = ObjectAccessor.GetPet(GetPlayer(), petguid); // check it! if (!pet || !pet.IsPet() || pet.ToPet().getPetType() != PetType.Hunter || !pet.HasPetFlag(UnitPetFlags.CanBeRenamed) || pet.GetOwnerGUID() != GetPlayer().GetGUID() || pet.GetCharmInfo() == null) { return; } PetNameInvalidReason res = ObjectManager.CheckPetName(name); if (res != PetNameInvalidReason.Success) { SendPetNameInvalid(res, name, null); return; } if (Global.ObjectMgr.IsReservedName(name)) { SendPetNameInvalid(PetNameInvalidReason.Reserved, name, null); return; } pet.SetName(name); pet.SetGroupUpdateFlag(GroupUpdatePetFlags.Name); pet.RemovePetFlag(UnitPetFlags.CanBeRenamed); PreparedStatement stmt; SQLTransaction trans = new SQLTransaction(); if (isdeclined) { stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_PET_DECLINEDNAME); stmt.AddValue(0, pet.GetCharmInfo().GetPetNumber()); trans.Append(stmt); stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PET_DECLINEDNAME); stmt.AddValue(0, pet.GetCharmInfo().GetPetNumber()); stmt.AddValue(1, GetPlayer().GetGUID().ToString()); for (byte i = 0; i < SharedConst.MaxDeclinedNameCases; i++) { stmt.AddValue(i + 1, packet.RenameData.DeclinedNames.name[i]); } trans.Append(stmt); } stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_CHAR_PET_NAME); stmt.AddValue(0, name); stmt.AddValue(1, GetPlayer().GetGUID().ToString()); stmt.AddValue(2, pet.GetCharmInfo().GetPetNumber()); trans.Append(stmt); DB.Characters.CommitTransaction(trans); pet.SetPetNameTimestamp((uint)Time.UnixTime); // cast can't be helped }
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 HandleSendMail(SendMail packet) { if (packet.Info.Attachments.Count > SharedConst.MaxClientMailItems) // 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; 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(); 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(packet.Info.Subject, packet.Info.Body); SQLTransaction trans = new(); 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); }