예제 #1
0
        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;
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        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));
        }
예제 #5
0
        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
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
        }