public bool UpdateWeather() { Player player = Global.WorldMgr.FindPlayerInZone(m_zone); if (player == null) { return(false); } // Send the weather packet to all players in this zone if (m_grade >= 1) { m_grade = 0.9999f; } else if (m_grade < 0) { m_grade = 0.0001f; } WeatherState state = GetWeatherState(); WeatherPkt weather = new WeatherPkt(state, m_grade); //- Returns false if there were no players found to update if (!Global.WorldMgr.SendZoneMessage(m_zone, weather)) { return(false); } // Log the event string wthstr; switch (state) { case WeatherState.Fog: wthstr = "fog"; break; case WeatherState.LightRain: wthstr = "light rain"; break; case WeatherState.MediumRain: wthstr = "medium rain"; break; case WeatherState.HeavyRain: wthstr = "heavy rain"; break; case WeatherState.LightSnow: wthstr = "light snow"; break; case WeatherState.MediumSnow: wthstr = "medium snow"; break; case WeatherState.HeavySnow: wthstr = "heavy snow"; break; case WeatherState.LightSandstorm: wthstr = "light sandstorm"; break; case WeatherState.MediumSandstorm: wthstr = "medium sandstorm"; break; case WeatherState.HeavySandstorm: wthstr = "heavy sandstorm"; break; case WeatherState.Thunders: wthstr = "thunders"; break; case WeatherState.BlackRain: wthstr = "blackrain"; break; case WeatherState.Fine: default: wthstr = "fine"; break; } Log.outInfo(LogFilter.Server, "Change the weather of zone {0} to {1}.", m_zone, wthstr); Global.ScriptMgr.OnWeatherChange(this, state, m_grade); return(true); }
public void LogoutPlayer(bool save) { // finish pending transfers before starting the logout while (_player && _player.IsBeingTeleportedFar()) { HandleMoveWorldportAck(); } m_playerLogout = true; m_playerSave = save; if (_player) { if (!_player.GetLootGUID().IsEmpty()) { DoLootReleaseAll(); } // If the player just died before logging out, make him appear as a ghost //FIXME: logout must be delayed in case lost connection with client in time of combat if (GetPlayer().GetDeathTimer() != 0) { _player.getHostileRefManager().deleteReferences(); _player.BuildPlayerRepop(); _player.RepopAtGraveyard(); } else if (GetPlayer().HasAuraType(AuraType.SpiritOfRedemption)) { // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION _player.RemoveAurasByType(AuraType.ModShapeshift); _player.KillPlayer(); _player.BuildPlayerRepop(); _player.RepopAtGraveyard(); } else if (GetPlayer().HasPendingBind()) { _player.RepopAtGraveyard(); _player.SetPendingBind(0, 0); } //drop a flag if player is carrying it Battleground bg = GetPlayer().GetBattleground(); if (bg) { bg.EventPlayerLoggedOut(GetPlayer()); } // Teleport to home if the player is in an invalid instance if (!_player.m_InstanceValid && !_player.IsGameMaster()) { _player.TeleportTo(_player.GetHomebind()); } Global.OutdoorPvPMgr.HandlePlayerLeaveZone(_player, _player.GetZoneId()); for (uint i = 0; i < SharedConst.MaxPlayerBGQueues; ++i) { BattlegroundQueueTypeId bgQueueTypeId = GetPlayer().GetBattlegroundQueueTypeId(i); if (bgQueueTypeId != 0) { _player.RemoveBattlegroundQueueId(bgQueueTypeId); BattlegroundQueue queue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId); queue.RemovePlayer(_player.GetGUID(), true); } } // Repop at GraveYard or other player far teleport will prevent saving player because of not present map // Teleport player immediately for correct player save while (_player.IsBeingTeleportedFar()) { HandleMoveWorldportAck(); } // If the player is in a guild, update the guild roster and broadcast a logout message to other guild members Guild guild = Global.GuildMgr.GetGuildById(_player.GetGuildId()); if (guild) { guild.HandleMemberLogout(this); } // Remove pet _player.RemovePet(null, PetSaveMode.AsCurrent, true); // Clear whisper whitelist _player.ClearWhisperWhiteList(); // empty buyback items and save the player in the database // some save parts only correctly work in case player present in map/player_lists (pets, etc) if (save) { for (int j = InventorySlots.BuyBackStart; j < InventorySlots.BuyBackEnd; ++j) { int eslot = j - InventorySlots.BuyBackStart; _player.SetGuidValue(PlayerFields.InvSlotHead + (j * 4), ObjectGuid.Empty); _player.SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0); _player.SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, 0); } _player.SaveToDB(); } // Leave all channels before player delete... _player.CleanupChannels(); // If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. _player.UninviteFromGroup(); // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) if (_player.GetGroup() && !_player.GetGroup().isRaidGroup() && m_Socket[(int)ConnectionType.Realm] != null) { _player.RemoveFromGroup(); } //! Send update to group and reset stored max enchanting level if (_player.GetGroup()) { _player.GetGroup().SendUpdate(); _player.GetGroup().ResetMaxEnchantingLevel(); } //! Broadcast a logout message to the player's friends Global.SocialMgr.SendFriendStatus(_player, FriendsResult.Offline, _player.GetGUID(), true); _player.RemoveSocial(); //! Call script hook before deletion Global.ScriptMgr.OnPlayerLogout(GetPlayer()); //! Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes GetPlayer().CleanupsBeforeDelete(); Log.outInfo(LogFilter.Player, "Account: {0} (IP: {1}) Logout Character:[{2}] (GUID: {3}) Level: {4}", GetAccountId(), GetRemoteAddress(), _player.GetName(), _player.GetGUID().ToString(), _player.getLevel()); Map map = GetPlayer().GetMap(); if (map != null) { map.RemovePlayerFromMap(GetPlayer(), true); } SetPlayer(null); //! Send the 'logout complete' packet to the client //! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle LogoutComplete logoutComplete = new LogoutComplete(); SendPacket(logoutComplete); //! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ACCOUNT_ONLINE); stmt.AddValue(0, GetAccountId()); DB.Characters.Execute(stmt); } if (m_Socket[(int)ConnectionType.Instance] != null) { m_Socket[(int)ConnectionType.Instance].CloseSocket(); m_Socket[(int)ConnectionType.Instance] = null; } m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; SetLogoutStartTime(0); }
public void LoadRBAC() { ClearRBAC(); Log.outDebug(LogFilter.Rbac, "AccountMgr:LoadRBAC"); uint oldMSTime = Time.GetMSTime(); uint count1 = 0; uint count2 = 0; uint count3 = 0; Log.outDebug(LogFilter.Rbac, "AccountMgr:LoadRBAC: Loading permissions"); SQLResult result = DB.Login.Query("SELECT id, name FROM rbac_permissions"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 account permission definitions. DB table `rbac_permissions` is empty."); return; } do { uint id = result.Read <uint>(0); _permissions[id] = new RBACPermission(id, result.Read <string>(1)); ++count1; }while (result.NextRow()); Log.outDebug(LogFilter.Rbac, "AccountMgr:LoadRBAC: Loading linked permissions"); result = DB.Login.Query("SELECT id, linkedId FROM rbac_linked_permissions ORDER BY id ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 linked permissions. DB table `rbac_linked_permissions` is empty."); return; } uint permissionId = 0; RBACPermission permission = null; do { uint newId = result.Read <uint>(0); if (permissionId != newId) { permissionId = newId; permission = _permissions[newId]; } uint linkedPermissionId = result.Read <uint>(1); if (linkedPermissionId == permissionId) { Log.outError(LogFilter.Sql, "RBAC Permission {0} has itself as linked permission. Ignored", permissionId); continue; } permission.AddLinkedPermission(linkedPermissionId); ++count2; }while (result.NextRow()); Log.outDebug(LogFilter.Rbac, "AccountMgr:LoadRBAC: Loading default permissions"); result = DB.Login.Query("SELECT secId, permissionId FROM rbac_default_permissions ORDER BY secId ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty."); return; } uint secId = 255; do { uint newId = result.Read <uint>(0); if (secId != newId) { secId = newId; } _defaultPermissions.Add((byte)secId, result.Read <uint>(1)); ++count3; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} permission definitions, {1} linked permissions and {2} default permissions in {3} ms", count1, count2, count3, Time.GetMSTimeDiffToNow(oldMSTime)); }
void HandleAuctionSellItem(AuctionSellItem packet) { foreach (var aitem in packet.Items) { if (aitem.Guid.IsEmpty() || aitem.UseCount == 0 || aitem.UseCount > 1000) { return; } } if (packet.MinBid == 0 || packet.RunTime == 0) { return; } if (packet.MinBid > PlayerConst.MaxMoneyAmount || packet.BuyoutPrice > PlayerConst.MaxMoneyAmount) { Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - Player {0} ({1}) attempted to sell item with higher price than max gold amount.", GetPlayer().GetName(), GetPlayer().GetGUID().ToString()); SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } Creature creature = GetPlayer().GetNPCIfCanInteractWith(packet.Auctioneer, NPCFlags.Auctioneer); if (!creature) { Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - {0} not found or you can't interact with him.", packet.Auctioneer.ToString()); return; } uint houseId = 0; AuctionHouseRecord auctionHouseEntry = Global.AuctionMgr.GetAuctionHouseEntry(creature.getFaction(), ref houseId); if (auctionHouseEntry == null) { Log.outDebug(LogFilter.Network, "WORLD: HandleAuctionSellItem - {0} has wrong faction.", packet.Auctioneer.ToString()); return; } packet.RunTime *= Time.Minute; switch (packet.RunTime) { case 1 * SharedConst.MinAuctionTime: case 2 * SharedConst.MinAuctionTime: case 4 * SharedConst.MinAuctionTime: break; default: return; } if (GetPlayer().HasUnitState(UnitState.Died)) { GetPlayer().RemoveAurasByType(AuraType.FeignDeath); } uint finalCount = 0; foreach (var packetItem in packet.Items) { Item aitem = GetPlayer().GetItemByGuid(packetItem.Guid); if (!aitem) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.ItemNotFound); return; } if (Global.AuctionMgr.GetAItem(aitem.GetGUID().GetCounter()) || !aitem.CanBeTraded() || aitem.IsNotEmptyBag() || aitem.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || aitem.GetUInt32Value(ItemFields.Duration) != 0 || aitem.GetCount() < packetItem.UseCount) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } finalCount += packetItem.UseCount; } if (packet.Items.Empty()) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } if (finalCount == 0) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } // check if there are 2 identical guids, in this case user is most likely cheating for (int i = 0; i < packet.Items.Count; ++i) { for (int j = i + 1; j < packet.Items.Count; ++j) { if (packet.Items[i].Guid == packet.Items[j].Guid) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } } } foreach (var packetItem in packet.Items) { Item aitem = GetPlayer().GetItemByGuid(packetItem.Guid); if (aitem.GetMaxStackCount() < finalCount) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } } Item item = GetPlayer().GetItemByGuid(packet.Items[0].Guid); uint auctionTime = (uint)(packet.RunTime * WorldConfig.GetFloatValue(WorldCfg.RateAuctionTime)); AuctionHouseObject auctionHouse = Global.AuctionMgr.GetAuctionsMap(creature.getFaction()); ulong deposit = Global.AuctionMgr.GetAuctionDeposit(auctionHouseEntry, packet.RunTime, item, finalCount); if (!GetPlayer().HasEnoughMoney(deposit)) { SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.NotEnoughtMoney); return; } AuctionEntry AH = new AuctionEntry(); SQLTransaction trans; if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionAuction)) { AH.auctioneer = 23442; ///@TODO - HARDCODED DB GUID, BAD BAD BAD } else { AH.auctioneer = creature.GetSpawnId(); } // Required stack size of auction matches to current item stack size, just move item to auctionhouse if (packet.Items.Count == 1 && item.GetCount() == packet.Items[0].UseCount) { if (HasPermission(RBACPermissions.LogGmTrade)) { Log.outCommand(GetAccountId(), "GM {0} (Account: {1}) create auction: {2} (Entry: {3} Count: {4})", GetPlayerName(), GetAccountId(), item.GetTemplate().GetName(), item.GetEntry(), item.GetCount()); } AH.Id = Global.ObjectMgr.GenerateAuctionID(); AH.itemGUIDLow = item.GetGUID().GetCounter(); AH.itemEntry = item.GetEntry(); AH.itemCount = item.GetCount(); AH.owner = GetPlayer().GetGUID().GetCounter(); AH.startbid = (uint)packet.MinBid; AH.bidder = 0; AH.bid = 0; AH.buyout = (uint)packet.BuyoutPrice; AH.expire_time = Time.UnixTime + auctionTime; AH.deposit = deposit; AH.etime = packet.RunTime; AH.auctionHouseEntry = auctionHouseEntry; Log.outInfo(LogFilter.Network, "CMSG_AUCTION_SELL_ITEM: {0} {1} is selling item {2} {3} to auctioneer {4} with count {5} with initial bid {6} with buyout {7} and with time {8} (in sec) in auctionhouse {9}", GetPlayer().GetGUID().ToString(), GetPlayer().GetName(), item.GetGUID().ToString(), item.GetTemplate().GetName(), AH.auctioneer, item.GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH.GetHouseId()); Global.AuctionMgr.AddAItem(item); auctionHouse.AddAuction(AH); GetPlayer().MoveItemFromInventory(item.GetBagSlot(), item.GetSlot(), true); trans = new SQLTransaction(); item.DeleteFromInventoryDB(trans); item.SaveToDB(trans); AH.SaveToDB(trans); GetPlayer().SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); SendAuctionCommandResult(AH, AuctionAction.SellItem, AuctionError.Ok); GetPlayer().UpdateCriteria(CriteriaTypes.CreateAuction, 1); } else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size { Item newItem = item.CloneItem(finalCount, GetPlayer()); if (!newItem) { Log.outError(LogFilter.Network, "CMSG_AuctionAction.SellItem: Could not create clone of item {0}", item.GetEntry()); SendAuctionCommandResult(null, AuctionAction.SellItem, AuctionError.DatabaseError); return; } if (HasPermission(RBACPermissions.LogGmTrade)) { Log.outCommand(GetAccountId(), "GM {0} (Account: {1}) create auction: {2} (Entry: {3} Count: {4})", GetPlayerName(), GetAccountId(), newItem.GetTemplate().GetName(), newItem.GetEntry(), newItem.GetCount()); } AH.Id = Global.ObjectMgr.GenerateAuctionID(); AH.itemGUIDLow = newItem.GetGUID().GetCounter(); AH.itemEntry = newItem.GetEntry(); AH.itemCount = newItem.GetCount(); AH.owner = GetPlayer().GetGUID().GetCounter(); AH.startbid = (uint)packet.MinBid; AH.bidder = 0; AH.bid = 0; AH.buyout = (uint)packet.BuyoutPrice; AH.expire_time = Time.UnixTime + auctionTime; AH.deposit = deposit; AH.etime = packet.RunTime; AH.auctionHouseEntry = auctionHouseEntry; Log.outInfo(LogFilter.Network, "CMSG_AuctionAction.SellItem: {0} {1} is selling {2} {3} to auctioneer {4} with count {5} with initial bid {6} with buyout {7} and with time {8} (in sec) in auctionhouse {9}", GetPlayer().GetGUID().ToString(), GetPlayer().GetName(), newItem.GetGUID().ToString(), newItem.GetTemplate().GetName(), AH.auctioneer, newItem.GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH.GetHouseId()); Global.AuctionMgr.AddAItem(newItem); auctionHouse.AddAuction(AH); foreach (var packetItem in packet.Items) { Item item2 = GetPlayer().GetItemByGuid(packetItem.Guid); // Item stack count equals required count, ready to delete item - cloned item will be used for auction if (item2.GetCount() == packetItem.UseCount) { GetPlayer().MoveItemFromInventory(item2.GetBagSlot(), item2.GetSlot(), true); trans = new SQLTransaction(); item2.DeleteFromInventoryDB(trans); item2.DeleteFromDB(trans); DB.Characters.CommitTransaction(trans); } else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction { item2.SetCount(item2.GetCount() - packetItem.UseCount); item2.SetState(ItemUpdateState.Changed, GetPlayer()); GetPlayer().ItemRemovedQuestCheck(item2.GetEntry(), packetItem.UseCount); item2.SendUpdateToPlayer(GetPlayer()); trans = new SQLTransaction(); item2.SaveToDB(trans); DB.Characters.CommitTransaction(trans); } } trans = new SQLTransaction(); newItem.SaveToDB(trans); AH.SaveToDB(trans); GetPlayer().SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); SendAuctionCommandResult(AH, AuctionAction.SellItem, AuctionError.Ok); GetPlayer().UpdateCriteria(CriteriaTypes.CreateAuction, 1); } GetPlayer().ModifyMoney(-(long)deposit); }
//todo fix me public bool EvaluateOpcode(WorldPacket packet, long time) { uint maxPacketCounterAllowed = 0;// GetMaxPacketCounterAllowed(p.GetOpcode()); // Return true if there no limit for the opcode if (maxPacketCounterAllowed == 0) { return(true); } if (!_PacketThrottlingMap.ContainsKey(packet.GetOpcode())) { _PacketThrottlingMap[packet.GetOpcode()] = new PacketCounter(); } PacketCounter packetCounter = _PacketThrottlingMap[packet.GetOpcode()]; if (packetCounter.lastReceiveTime != time) { packetCounter.lastReceiveTime = time; packetCounter.amountCounter = 0; } // Check if player is flooding some packets if (++packetCounter.amountCounter <= maxPacketCounterAllowed) { return(true); } Log.outWarn(LogFilter.Network, "AntiDOS: Account {0}, IP: {1}, Ping: {2}, Character: {3}, flooding packet (opc: {4} (0x{4}), count: {5})", Session.GetAccountId(), Session.GetRemoteAddress(), Session.GetLatency(), Session.GetPlayerName(), packet.GetOpcode(), packetCounter.amountCounter); switch (_policy) { case Policy.Log: return(true); case Policy.Kick: Log.outInfo(LogFilter.Network, "AntiDOS: Player kicked!"); return(false); case Policy.Ban: BanMode bm = (BanMode)WorldConfig.GetIntValue(WorldCfg.PacketSpoofBanmode); uint duration = WorldConfig.GetUIntValue(WorldCfg.PacketSpoofBanduration); // in seconds string nameOrIp = ""; switch (bm) { case BanMode.Character: // not supported, ban account case BanMode.Account: Global.AccountMgr.GetName(Session.GetAccountId(), out nameOrIp); break; case BanMode.IP: nameOrIp = Session.GetRemoteAddress(); break; } Global.WorldMgr.BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); Log.outInfo(LogFilter.Network, "AntiDOS: Player automatically banned for {0} seconds.", duration); return(false); } return(true); }
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 CreatureTextEntry(); 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)); }
public void LoadGuilds() { Log.outInfo(LogFilter.ServerLoading, "Loading Guilds Definitions..."); { uint oldMSTime = Time.GetMSTime(); // 0 1 2 3 4 5 6 SQLResult result = DB.Characters.Query("SELECT g.guildid, g.name, g.leaderguid, g.EmblemStyle, g.EmblemColor, g.BorderStyle, g.BorderColor, " + // 7 8 9 10 11 12 "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, COUNT(gbt.guildid) " + "FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.Guild, "Loaded 0 guild definitions. DB table `guild` is empty."); return; } uint count = 0; do { Guild guild = new(); if (!guild.LoadFromDB(result.GetFields())) { continue; } AddGuild(guild); count++; } while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } Log.outInfo(LogFilter.ServerLoading, "Loading guild ranks..."); { uint oldMSTime = Time.GetMSTime(); // Delete orphaned guild rank entries before loading the valid ones DB.Characters.DirectExecute("DELETE gr FROM guild_rank gr LEFT JOIN guild g ON gr.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 SQLResult result = DB.Characters.Query("SELECT guildid, rid, rname, rights, BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild ranks. DB table `guild_rank` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadRankFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild ranks in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 3. Load all guild members Log.outInfo(LogFilter.ServerLoading, "Loading guild members..."); { uint oldMSTime = Time.GetMSTime(); // Delete orphaned guild member entries before loading the valid ones DB.Characters.DirectExecute("DELETE gm FROM guild_member gm LEFT JOIN guild g ON gm.guildId = g.guildId WHERE g.guildId IS NULL"); DB.Characters.DirectExecute("DELETE gm FROM guild_member_withdraw gm LEFT JOIN guild_member g ON gm.guid = g.guid WHERE g.guid IS NULL"); // 0 1 2 3 4 5 6 7 8 9 10 SQLResult result = DB.Characters.Query("SELECT gm.guildid, gm.guid, rank, pnote, offnote, w.tab0, w.tab1, w.tab2, w.tab3, w.tab4, w.tab5, " + // 11 12 13 14 15 16 17 18 19 20 "w.tab6, w.tab7, w.money, c.name, c.level, c.class, c.gender, c.zone, c.account, c.logout_time " + "FROM guild_member gm LEFT JOIN guild_member_withdraw w ON gm.guid = w.guid " + "LEFT JOIN characters c ON c.guid = gm.guid ORDER BY gm.guildid ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild members. DB table `guild_member` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadMemberFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild members in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 4. Load all guild bank tab rights Log.outInfo(LogFilter.ServerLoading, "Loading bank tab rights..."); { uint oldMSTime = Time.GetMSTime(); // Delete orphaned guild bank right entries before loading the valid ones DB.Characters.DirectExecute("DELETE gbr FROM guild_bank_right gbr LEFT JOIN guild g ON gbr.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 SQLResult result = DB.Characters.Query("SELECT guildid, TabId, rid, gbright, SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild bank tab rights. DB table `guild_bank_right` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadBankRightFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} bank tab rights in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 5. Load all event logs Log.outInfo(LogFilter.ServerLoading, "Loading guild event logs..."); { uint oldMSTime = Time.GetMSTime(); DB.Characters.DirectExecute("DELETE FROM guild_eventlog WHERE LogGuid > {0}", GuildConst.EventLogMaxRecords); // 0 1 2 3 4 5 6 SQLResult result = DB.Characters.Query("SELECT guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp FROM guild_eventlog ORDER BY TimeStamp DESC, LogGuid DESC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild event logs. DB table `guild_eventlog` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadEventLogFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild event logs in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 6. Load all bank event logs Log.outInfo(LogFilter.ServerLoading, "Loading guild bank event logs..."); { uint oldMSTime = Time.GetMSTime(); // Remove log entries that exceed the number of allowed entries per guild DB.Characters.DirectExecute("DELETE FROM guild_bank_eventlog WHERE LogGuid > {0}", GuildConst.BankLogMaxRecords); // 0 1 2 3 4 5 6 7 8 SQLResult result = DB.Characters.Query("SELECT guildid, TabId, LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog ORDER BY TimeStamp DESC, LogGuid DESC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild bank event logs. DB table `guild_bank_eventlog` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadBankEventLogFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild bank event logs in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 7. Load all news event logs Log.outInfo(LogFilter.ServerLoading, "Loading Guild News..."); { uint oldMSTime = Time.GetMSTime(); DB.Characters.DirectExecute("DELETE FROM guild_newslog WHERE LogGuid > {0}", GuildConst.NewsLogMaxRecords); // 0 1 2 3 4 5 6 SQLResult result = DB.Characters.Query("SELECT guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp FROM guild_newslog ORDER BY TimeStamp DESC, LogGuid DESC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild event logs. DB table `guild_newslog` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadGuildNewsLogFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild new logs in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 8. Load all guild bank tabs Log.outInfo(LogFilter.ServerLoading, "Loading guild bank tabs..."); { uint oldMSTime = Time.GetMSTime(); // Delete orphaned guild bank tab entries before loading the valid ones DB.Characters.DirectExecute("DELETE gbt FROM guild_bank_tab gbt LEFT JOIN guild g ON gbt.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 SQLResult result = DB.Characters.Query("SELECT guildid, TabId, TabName, TabIcon, TabText FROM guild_bank_tab ORDER BY guildid ASC, TabId ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild bank tabs. DB table `guild_bank_tab` is empty."); } else { uint count = 0; do { uint guildId = result.Read <uint>(0); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadBankTabFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild bank tabs in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 9. Fill all guild bank tabs Log.outInfo(LogFilter.ServerLoading, "Filling bank tabs with items..."); { uint oldMSTime = Time.GetMSTime(); // Delete orphan guild bank items DB.Characters.DirectExecute("DELETE gbi FROM guild_bank_item gbi LEFT JOIN guild g ON gbi.guildId = g.guildId WHERE g.guildId IS NULL"); SQLResult result = DB.Characters.Query(DB.Characters.GetPreparedStatement(CharStatements.SEL_GUILD_BANK_ITEMS)); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 guild bank tab items. DB table `guild_bank_item` or `item_instance` is empty."); } else { uint count = 0; do { ulong guildId = result.Read <ulong>(43); Guild guild = GetGuildById(guildId); if (guild) { guild.LoadBankItemFromDB(result.GetFields()); } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} guild bank tab items in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // 10. Load guild achievements Log.outInfo(LogFilter.ServerLoading, "Loading guild achievements..."); { uint oldMSTime = Time.GetMSTime(); foreach (var pair in GuildStore) { PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_GUILD_ACHIEVEMENT); stmt.AddValue(0, pair.Key); SQLResult achievementResult = DB.Characters.Query(stmt); stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_GUILD_ACHIEVEMENT_CRITERIA); stmt.AddValue(0, pair.Key); SQLResult criteriaResult = DB.Characters.Query(stmt); pair.Value.GetAchievementMgr().LoadFromDB(achievementResult, criteriaResult); } Log.outInfo(LogFilter.ServerLoading, "Loaded guild achievements and criterias in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime)); } // 11. Validate loaded guild data Log.outInfo(LogFilter.Server, "Validating data of loaded guilds..."); { uint oldMSTime = Time.GetMSTime(); foreach (var guild in GuildStore.ToList()) { if (!guild.Value.Validate()) { GuildStore.Remove(guild.Key); } } Log.outInfo(LogFilter.ServerLoading, "Validated data of loaded guilds in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime)); } }
public void LoadDisables() { uint oldMSTime = Time.GetMSTime(); // reload case m_DisableMap.Clear(); SQLResult result = DB.World.Query("SELECT sourceType, entry, flags, params_0, params_1 FROM disables"); if (result.IsEmpty()) { Log.outError(LogFilter.ServerLoading, "Loaded 0 disables. DB table `disables` is empty!"); return; } uint total_count = 0; do { DisableType type = (DisableType)result.Read <uint>(0); if (type >= DisableType.Max) { Log.outError(LogFilter.Sql, "Invalid type {0} specified in `disables` table, skipped.", type); continue; } uint entry = result.Read <uint>(1); byte flags = result.Read <byte>(2); string params_0 = result.Read <string>(3); string params_1 = result.Read <string>(4); DisableData data = new DisableData(); data.flags = flags; switch (type) { case DisableType.Spell: if (!(Global.SpellMgr.HasSpellInfo(entry) || flags.HasAnyFlag <byte>(DisableFlags.SpellDeprecatedSpell))) { Log.outError(LogFilter.Sql, "Spell entry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (flags == 0 || flags > DisableFlags.MaxSpell) { Log.outError(LogFilter.Sql, "Disable flags for spell {0} are invalid, skipped.", entry); continue; } if (flags.HasAnyFlag <byte>(DisableFlags.SpellMap)) { var array = new StringArray(params_0, ','); for (byte i = 0; i < array.Length;) { data.param0.Add(uint.Parse(array[i++])); } } if (flags.HasAnyFlag <byte>(DisableFlags.SpellArea)) { var array = new StringArray(params_1, ','); for (byte i = 0; i < array.Length;) { data.param1.Add(uint.Parse(array[i++])); } } break; // checked later case DisableType.Quest: break; case DisableType.Map: { MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry); if (mapEntry == null) { Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } bool isFlagInvalid = false; switch (mapEntry.InstanceType) { case MapTypes.Common: if (flags != 0) { isFlagInvalid = true; } break; case MapTypes.Instance: case MapTypes.Raid: if (flags.HasAnyFlag <byte>(DisableFlags.DungeonStatusHeroic) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Heroic) == null) { flags -= DisableFlags.DungeonStatusHeroic; } if (flags.HasAnyFlag <byte>(DisableFlags.DungeonStatusHeroic10Man) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Raid10HC) == null) { flags -= DisableFlags.DungeonStatusHeroic10Man; } if (flags.HasAnyFlag <byte>(DisableFlags.DungeonStatusHeroic25Man) && Global.DB2Mgr.GetMapDifficultyData(entry, Difficulty.Raid25HC) == null) { flags -= DisableFlags.DungeonStatusHeroic25Man; } if (flags == 0) { isFlagInvalid = true; } break; case MapTypes.Battleground: case MapTypes.Arena: Log.outError(LogFilter.Sql, "Battlegroundmap {0} specified to be disabled in map case, skipped.", entry); continue; } if (isFlagInvalid) { Log.outError(LogFilter.Sql, "Disable flags for map {0} are invalid, skipped.", entry); continue; } break; } case DisableType.Battleground: if (!CliDB.BattlemasterListStorage.ContainsKey(entry)) { Log.outError(LogFilter.Sql, "Battlegroundentry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (flags != 0) { Log.outError(LogFilter.Sql, "Disable flags specified for Battleground{0}, useless data.", entry); } break; case DisableType.OutdoorPVP: if (entry > (int)OutdoorPvPTypes.Max) { Log.outError(LogFilter.Sql, "OutdoorPvPTypes value {0} from `disables` is invalid, skipped.", entry); continue; } if (flags != 0) { Log.outError(LogFilter.Sql, "Disable flags specified for outdoor PvP {0}, useless data.", entry); } break; case DisableType.Criteria: if (Global.CriteriaMgr.GetCriteria(entry) == null) { Log.outError(LogFilter.Sql, "Criteria entry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } if (flags != 0) { Log.outError(LogFilter.Sql, "Disable flags specified for Criteria {0}, useless data.", entry); } break; case DisableType.VMAP: { MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry); if (mapEntry == null) { Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } switch (mapEntry.InstanceType) { case MapTypes.Common: if (flags.HasAnyFlag(DisableFlags.VmapAreaFlag)) { Log.outInfo(LogFilter.Server, "Areaflag disabled for world map {0}.", entry); } if (flags.HasAnyFlag(DisableFlags.VmapLiquidStatus)) { Log.outInfo(LogFilter.Server, "Liquid status disabled for world map {0}.", entry); } break; case MapTypes.Instance: case MapTypes.Raid: if (flags.HasAnyFlag(DisableFlags.VmapHeight)) { Log.outInfo(LogFilter.Server, "Height disabled for instance map {0}.", entry); } if (flags.HasAnyFlag(DisableFlags.VmapLOS)) { Log.outInfo(LogFilter.Server, "LoS disabled for instance map {0}.", entry); } break; case MapTypes.Battleground: if (flags.HasAnyFlag(DisableFlags.VmapHeight)) { Log.outInfo(LogFilter.Server, "Height disabled for Battlegroundmap {0}.", entry); } if (flags.HasAnyFlag(DisableFlags.VmapLOS)) { Log.outInfo(LogFilter.Server, "LoS disabled for Battlegroundmap {0}.", entry); } break; case MapTypes.Arena: if (flags.HasAnyFlag(DisableFlags.VmapHeight)) { Log.outInfo(LogFilter.Server, "Height disabled for arena map {0}.", entry); } if (flags.HasAnyFlag(DisableFlags.VmapLOS)) { Log.outInfo(LogFilter.Server, "LoS disabled for arena map {0}.", entry); } break; default: break; } break; } case DisableType.MMAP: { MapRecord mapEntry = CliDB.MapStorage.LookupByKey(entry); if (mapEntry == null) { Log.outError(LogFilter.Sql, "Map entry {0} from `disables` doesn't exist in dbc, skipped.", entry); continue; } switch (mapEntry.InstanceType) { case MapTypes.Common: Log.outInfo(LogFilter.Server, "Pathfinding disabled for world map {0}.", entry); break; case MapTypes.Instance: case MapTypes.Raid: Log.outInfo(LogFilter.Server, "Pathfinding disabled for instance map {0}.", entry); break; case MapTypes.Battleground: Log.outInfo(LogFilter.Server, "Pathfinding disabled for Battlegroundmap {0}.", entry); break; case MapTypes.Arena: Log.outInfo(LogFilter.Server, "Pathfinding disabled for arena map {0}.", entry); break; default: break; } break; } default: break; } if (!m_DisableMap.ContainsKey(type)) { m_DisableMap[type] = new Dictionary <uint, DisableData>(); } m_DisableMap[type].Add(entry, data); ++total_count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} disables in {1} ms", total_count, Time.GetMSTimeDiffToNow(oldMSTime)); }
public void LoadFromDB() { // Pool templates { uint oldMSTime = Time.GetMSTime(); SQLResult result = DB.World.Query("SELECT entry, max_limit FROM pool_template"); if (result.IsEmpty()) { mPoolTemplate.Clear(); Log.outInfo(LogFilter.ServerLoading, "Loaded 0 object pools. DB table `pool_template` is empty."); return; } uint count = 0; do { uint pool_id = result.Read <uint>(0); PoolTemplateData pPoolTemplate = new(); pPoolTemplate.MaxLimit = result.Read <uint>(1); mPoolTemplate[pool_id] = pPoolTemplate; ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} objects pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } // Creatures Log.outInfo(LogFilter.ServerLoading, "Loading Creatures Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT spawnId, poolSpawnId, chance FROM pool_members WHERE type = 0"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 creatures in pools. DB table `pool_creature` is empty."); } else { uint count = 0; do { ulong guid = result.Read <ulong>(0); uint pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); CreatureData data = Global.ObjectMgr.GetCreatureData(guid); if (data == null) { Log.outError(LogFilter.Sql, "`pool_creature` has a non existing creature spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id); continue; } if (!mPoolTemplate.ContainsKey(pool_id)) { Log.outError(LogFilter.Sql, "`pool_creature` pool id ({0}) is not in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_creature` has an invalid chance ({0}) for creature guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id); continue; } PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id]; PoolObject plObject = new(guid, chance); if (!mPoolCreatureGroups.ContainsKey(pool_id)) { mPoolCreatureGroups[pool_id] = new PoolGroup <Creature>(); } PoolGroup <Creature> cregroup = mPoolCreatureGroups[pool_id]; cregroup.SetPoolId(pool_id); cregroup.AddEntry(plObject, pPoolTemplate.MaxLimit); mCreatureSearchMap.Add(guid, pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creatures in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // Gameobjects Log.outInfo(LogFilter.ServerLoading, "Loading Gameobject Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT spawnId, poolSpawnId, chance FROM pool_members WHERE type = 1"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty."); } else { uint count = 0; do { ulong guid = result.Read <ulong>(0); uint pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); GameObjectData data = Global.ObjectMgr.GetGameObjectData(guid); if (data == null) { Log.outError(LogFilter.Sql, "`pool_gameobject` has a non existing gameobject spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id); continue; } GameObjectTemplate goinfo = Global.ObjectMgr.GetGameObjectTemplate(data.Id); if (goinfo.type != GameObjectTypes.Chest && goinfo.type != GameObjectTypes.FishingHole && goinfo.type != GameObjectTypes.GatheringNode && goinfo.type != GameObjectTypes.Goober) { Log.outError(LogFilter.Sql, "`pool_gameobject` has a not lootable gameobject spawn (GUID: {0}, type: {1}) defined for pool id ({2}), skipped.", guid, goinfo.type, pool_id); continue; } if (!mPoolTemplate.ContainsKey(pool_id)) { Log.outError(LogFilter.Sql, "`pool_gameobject` pool id ({0}) is not in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_gameobject` has an invalid chance ({0}) for gameobject guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id); continue; } PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id]; PoolObject plObject = new(guid, chance); if (!mPoolGameobjectGroups.ContainsKey(pool_id)) { mPoolGameobjectGroups[pool_id] = new PoolGroup <GameObject>(); } PoolGroup <GameObject> gogroup = mPoolGameobjectGroups[pool_id]; gogroup.SetPoolId(pool_id); gogroup.AddEntry(plObject, pPoolTemplate.MaxLimit); mGameobjectSearchMap.Add(guid, pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} gameobject in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // Pool of pools Log.outInfo(LogFilter.ServerLoading, "Loading Mother Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT spawnId, poolSpawnId, chance FROM pool_members WHERE type = 2"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 pools in pools"); } else { uint count = 0; do { uint child_pool_id = result.Read <uint>(0); uint mother_pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); if (!mPoolTemplate.ContainsKey(mother_pool_id)) { Log.outError(LogFilter.Sql, "`pool_pool` mother_pool id ({0}) is not in `pool_template`, skipped.", mother_pool_id); continue; } if (!mPoolTemplate.ContainsKey(child_pool_id)) { Log.outError(LogFilter.Sql, "`pool_pool` included pool_id ({0}) is not in `pool_template`, skipped.", child_pool_id); continue; } if (mother_pool_id == child_pool_id) { Log.outError(LogFilter.Sql, "`pool_pool` pool_id ({0}) includes itself, dead-lock detected, skipped.", child_pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_pool` has an invalid chance ({0}) for pool id ({1}) in mother pool id ({2}), skipped.", chance, child_pool_id, mother_pool_id); continue; } PoolTemplateData pPoolTemplateMother = mPoolTemplate[mother_pool_id]; PoolObject plObject = new(child_pool_id, chance); if (!mPoolPoolGroups.ContainsKey(mother_pool_id)) { mPoolPoolGroups[mother_pool_id] = new PoolGroup <Pool>(); } PoolGroup <Pool> plgroup = mPoolPoolGroups[mother_pool_id]; plgroup.SetPoolId(mother_pool_id); plgroup.AddEntry(plObject, pPoolTemplateMother.MaxLimit); mPoolSearchMap.Add(child_pool_id, mother_pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} pools in mother pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks Log.outInfo(LogFilter.ServerLoading, "Starting objects pooling system..."); { uint oldMSTime = Time.GetMSTime(); SQLResult result = DB.World.Query("SELECT DISTINCT pool_template.entry, pool_members.spawnId, pool_members.poolSpawnId FROM pool_template" + " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry" + " LEFT JOIN pool_members ON pool_members.type = 2 AND pool_template.entry = pool_members.spawnId WHERE game_event_pool.pool_entry IS NULL"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Pool handling system initialized, 0 pools spawned."); } else { uint count = 0; do { uint pool_entry = result.Read <uint>(0); uint pool_pool_id = result.Read <uint>(1); if (!CheckPool(pool_entry)) { if (pool_pool_id != 0) { // The pool is a child pool in pool_pool table. Ideally we should remove it from the pool handler to ensure it never gets spawned, // however that could recursively invalidate entire chain of mother pools. It can be done in the future but for now we'll do nothing. Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id {1} and cannot be safely removed.", pool_entry, result.Read <uint>(2)); } else { Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry); } continue; } // Don't spawn child pools, they are spawned recursively by their parent pools if (pool_pool_id == 0) { SpawnPool(pool_entry); count++; } }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Pool handling system initialized, {0} pools spawned in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } }
public bool loadMap(uint mapId, int x, int y) { // make sure the mmap is loaded and ready to load tiles if (!loadMapData(mapId)) { return(false); } // get this mmap data MMapData mmap = loadedMMaps[mapId]; Contract.Assert(mmap.navMesh != null); // check if we already have this tile loaded uint packedGridPos = packTileID(x, y); if (mmap.loadedTileRefs.ContainsKey(packedGridPos)) { return(false); } // load this tile . mmaps/MMMXXYY.mmtile string filename = string.Format(TILE_FILE_NAME_FORMAT, Global.WorldMgr.GetDataPath(), mapId, x, y); if (!File.Exists(filename)) { Log.outDebug(LogFilter.Maps, "MMAP:loadMap: Could not open mmtile file '{0}'", filename); return(false); } using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read))) { MmapTileHeader fileHeader = reader.ReadStruct <MmapTileHeader>(); Array.Reverse(fileHeader.mmapMagic); if (new string(fileHeader.mmapMagic) != MapConst.mmapMagic) { Log.outError(LogFilter.Maps, "MMAP:loadMap: Bad header in mmap {0:D4}{1:D2}{2:D2}.mmtile", mapId, x, y); return(false); } if (fileHeader.mmapVersion != MapConst.mmapVersion) { Log.outError(LogFilter.Maps, "MMAP:loadMap: {0:D4}{1:D2}{2:D2}.mmtile was built with generator v{3}, expected v{4}", mapId, x, y, fileHeader.mmapVersion, MapConst.mmapVersion); return(false); } var bytes = reader.ReadBytes((int)fileHeader.size); Detour.dtRawTileData data = new Detour.dtRawTileData(); data.FromBytes(bytes, 0); ulong tileRef = 0; // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed if (Detour.dtStatusSucceed(mmap.navMesh.addTile(data, 0, 0, ref tileRef))) { mmap.loadedTileRefs.Add(packedGridPos, tileRef); ++loadedTiles; Log.outInfo(LogFilter.Maps, "MMAP:loadMap: Loaded mmtile {0:D4}[{1:D2}, {2:D2}]", mapId, x, y); return(true); } Log.outError(LogFilter.Maps, "MMAP:loadMap: Could not load {0:D4}{1:D2}{2:D2}.mmtile into navmesh", mapId, x, y); return(false); } }
public void LoadFromDB() { // Pool templates { uint oldMSTime = Time.GetMSTime(); SQLResult result = DB.World.Query("SELECT entry, max_limit FROM pool_template"); if (result.IsEmpty()) { mPoolTemplate.Clear(); Log.outInfo(LogFilter.ServerLoading, "Loaded 0 object pools. DB table `pool_template` is empty."); return; } uint count = 0; do { uint pool_id = result.Read <uint>(0); PoolTemplateData pPoolTemplate = new PoolTemplateData(); pPoolTemplate.MaxLimit = result.Read <uint>(1); mPoolTemplate[pool_id] = pPoolTemplate; ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} objects pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } // Creatures Log.outInfo(LogFilter.ServerLoading, "Loading Creatures Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT guid, pool_entry, chance FROM pool_creature"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 creatures in pools. DB table `pool_creature` is empty."); } else { uint count = 0; do { ulong guid = result.Read <ulong>(0); uint pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); CreatureData data = Global.ObjectMgr.GetCreatureData(guid); if (data == null) { Log.outError(LogFilter.Sql, "`pool_creature` has a non existing creature spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id); continue; } if (!mPoolTemplate.ContainsKey(pool_id)) { Log.outError(LogFilter.Sql, "`pool_creature` pool id ({0}) is not in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_creature` has an invalid chance ({0}) for creature guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id); continue; } PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id]; PoolObject plObject = new PoolObject(guid, chance); if (!mPoolCreatureGroups.ContainsKey(pool_id)) { mPoolCreatureGroups[pool_id] = new PoolGroup <Creature>(); } PoolGroup <Creature> cregroup = mPoolCreatureGroups[pool_id]; cregroup.SetPoolId(pool_id); cregroup.AddEntry(plObject, pPoolTemplate.MaxLimit); mCreatureSearchMap.Add(guid, pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creatures in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // Gameobjects Log.outInfo(LogFilter.ServerLoading, "Loading Gameobject Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT guid, pool_entry, chance FROM pool_gameobject"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty."); } else { uint count = 0; do { ulong guid = result.Read <ulong>(0); uint pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); GameObjectData data = Global.ObjectMgr.GetGOData(guid); if (data == null) { Log.outError(LogFilter.Sql, "`pool_gameobject` has a non existing gameobject spawn (GUID: {0}) defined for pool id ({1}), skipped.", guid, pool_id); continue; } GameObjectTemplate goinfo = Global.ObjectMgr.GetGameObjectTemplate(data.id); if (goinfo.type != GameObjectTypes.Chest && goinfo.type != GameObjectTypes.FishingHole && goinfo.type != GameObjectTypes.GatheringNode && goinfo.type != GameObjectTypes.Goober) { Log.outError(LogFilter.Sql, "`pool_gameobject` has a not lootable gameobject spawn (GUID: {0}, type: {1}) defined for pool id ({2}), skipped.", guid, goinfo.type, pool_id); continue; } if (!mPoolTemplate.ContainsKey(pool_id)) { Log.outError(LogFilter.Sql, "`pool_gameobject` pool id ({0}) is not in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_gameobject` has an invalid chance ({0}) for gameobject guid ({1}) in pool id ({2}), skipped.", chance, guid, pool_id); continue; } PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id]; PoolObject plObject = new PoolObject(guid, chance); if (!mPoolGameobjectGroups.ContainsKey(pool_id)) { mPoolGameobjectGroups[pool_id] = new PoolGroup <GameObject>(); } PoolGroup <GameObject> gogroup = mPoolGameobjectGroups[pool_id]; gogroup.SetPoolId(pool_id); gogroup.AddEntry(plObject, pPoolTemplate.MaxLimit); mGameobjectSearchMap.Add(guid, pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} gameobject in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // Pool of pools Log.outInfo(LogFilter.ServerLoading, "Loading Mother Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); // 1 2 3 SQLResult result = DB.World.Query("SELECT pool_id, mother_pool, chance FROM pool_pool"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 pools in pools"); } else { uint count = 0; do { uint child_pool_id = result.Read <uint>(0); uint mother_pool_id = result.Read <uint>(1); float chance = result.Read <float>(2); if (!mPoolTemplate.ContainsKey(mother_pool_id)) { Log.outError(LogFilter.Sql, "`pool_pool` mother_pool id ({0}) is not in `pool_template`, skipped.", mother_pool_id); continue; } if (!mPoolTemplate.ContainsKey(child_pool_id)) { Log.outError(LogFilter.Sql, "`pool_pool` included pool_id ({0}) is not in `pool_template`, skipped.", child_pool_id); continue; } if (mother_pool_id == child_pool_id) { Log.outError(LogFilter.Sql, "`pool_pool` pool_id ({0}) includes itself, dead-lock detected, skipped.", child_pool_id); continue; } if (chance < 0 || chance > 100) { Log.outError(LogFilter.Sql, "`pool_pool` has an invalid chance ({0}) for pool id ({1}) in mother pool id ({2}), skipped.", chance, child_pool_id, mother_pool_id); continue; } PoolTemplateData pPoolTemplateMother = mPoolTemplate[mother_pool_id]; PoolObject plObject = new PoolObject(child_pool_id, chance); if (!mPoolPoolGroups.ContainsKey(mother_pool_id)) { mPoolPoolGroups[mother_pool_id] = new PoolGroup <Pool>(); } PoolGroup <Pool> plgroup = mPoolPoolGroups[mother_pool_id]; plgroup.SetPoolId(mother_pool_id); plgroup.AddEntry(plObject, pPoolTemplateMother.MaxLimit); mPoolSearchMap.Add(child_pool_id, mother_pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} pools in mother pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } Log.outInfo(LogFilter.ServerLoading, "Loading Quest Pooling Data..."); { uint oldMSTime = Time.GetMSTime(); PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.SEL_QUEST_POOLS); SQLResult result = DB.World.Query(stmt); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 quests in pools"); } else { List <uint> creBounds; List <uint> goBounds; Dictionary <uint, eQuestTypes> poolTypeMap = new Dictionary <uint, eQuestTypes>(); uint count = 0; do { uint entry = result.Read <uint>(0); uint pool_id = result.Read <uint>(1); if (!poolTypeMap.ContainsKey(pool_id)) { poolTypeMap[pool_id] = 0; } Quest quest = Global.ObjectMgr.GetQuestTemplate(entry); if (quest == null) { Log.outError(LogFilter.Sql, "`pool_quest` has a non existing quest template (Entry: {0}) defined for pool id ({1}), skipped.", entry, pool_id); continue; } if (!mPoolTemplate.ContainsKey(pool_id)) { Log.outError(LogFilter.Sql, "`pool_quest` pool id ({0}) is not in `pool_template`, skipped.", pool_id); continue; } if (!quest.IsDailyOrWeekly()) { Log.outError(LogFilter.Sql, "`pool_quest` has an quest ({0}) which is not daily or weekly in pool id ({1}), use ExclusiveGroup instead, skipped.", entry, pool_id); continue; } if (poolTypeMap[pool_id] == eQuestTypes.None) { poolTypeMap[pool_id] = quest.IsDaily() ? eQuestTypes.Daily : eQuestTypes.Weekly; } eQuestTypes currType = quest.IsDaily() ? eQuestTypes.Daily : eQuestTypes.Weekly; if (poolTypeMap[pool_id] != currType) { Log.outError(LogFilter.Sql, "`pool_quest` quest {0} is {1} but pool ({2}) is specified for {3}, mixing not allowed, skipped.", entry, currType, pool_id, poolTypeMap[pool_id]); continue; } creBounds = mQuestCreatureRelation.LookupByKey(entry); goBounds = mQuestGORelation.LookupByKey(entry); if (creBounds.Empty() && goBounds.Empty()) { Log.outError(LogFilter.Sql, "`pool_quest` lists entry ({0}) as member of pool ({1}) but is not started anywhere, skipped.", entry, pool_id); continue; } PoolTemplateData pPoolTemplate = mPoolTemplate[pool_id]; PoolObject plObject = new PoolObject(entry, 0.0f); if (!mPoolQuestGroups.ContainsKey(pool_id)) { mPoolQuestGroups[pool_id] = new PoolGroup <Quest>(); } PoolGroup <Quest> questgroup = mPoolQuestGroups[pool_id]; questgroup.SetPoolId(pool_id); questgroup.AddEntry(plObject, pPoolTemplate.MaxLimit); mQuestSearchMap.Add(entry, pool_id); ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} quests in pools in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks Log.outInfo(LogFilter.ServerLoading, "Starting objects pooling system..."); { uint oldMSTime = Time.GetMSTime(); SQLResult result = DB.World.Query("SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool FROM pool_template" + " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry" + " LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Pool handling system initialized, 0 pools spawned."); } else { uint count = 0; do { uint pool_entry = result.Read <uint>(0); uint pool_pool_id = result.Read <uint>(1); if (!CheckPool(pool_entry)) { if (pool_pool_id != 0) { // The pool is a child pool in pool_pool table. Ideally we should remove it from the pool handler to ensure it never gets spawned, // however that could recursively invalidate entire chain of mother pools. It can be done in the future but for now we'll do nothing. Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id {1} and cannot be safely removed.", pool_entry, result.Read <uint>(2)); } else { Log.outError(LogFilter.Sql, "Pool Id {0} has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry); } continue; } // Don't spawn child pools, they are spawned recursively by their parent pools if (pool_pool_id == 0) { SpawnPool(pool_entry); count++; } }while (result.NextRow()); Log.outDebug(LogFilter.Pool, "Pool handling system initialized, {0} pools spawned in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } } }
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 = ObjectManager.GetPlayerGUIDByName(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; if (receiver) { receiverTeam = receiver.GetTeam(); mailsCount = (byte)receiver.GetMails().Count; receiverLevel = (byte)receiver.getLevel(); receiverAccountId = receiver.GetSession().GetAccountId(); } else { receiverTeam = ObjectManager.GetPlayerTeamByGUID(receiverGuid); 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); } stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_LEVEL); stmt.AddValue(0, receiverGuid.GetCounter()); result = DB.Characters.Query(stmt); if (!result.IsEmpty()) { receiverLevel = result.Read <byte>(0); } receiverAccountId = ObjectManager.GetPlayerAccountIdByGUID(receiverGuid); } // 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) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.NotSameAccount); return; } if (item.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || item.GetUInt32Value(ItemFields.Duration) != 0) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (packet.Info.Cod != 0 && item.HasFlag(ItemFields.Flags, 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); }
void HandleMailCreateTextItem(MailCreateTextItem packet) { if (!CanOpenMailBox(packet.Mailbox)) { return; } Player player = GetPlayer(); Mail m = player.GetMail(packet.MailID); if (m == null || (string.IsNullOrEmpty(m.body) && m.mailTemplateId == 0) || m.state == MailState.Deleted || m.deliver_time > Time.UnixTime) { player.SendMailResult(packet.MailID, MailResponseType.MadePermanent, MailResponseResult.InternalError); return; } Item bodyItem = new Item(); // This is not bag and then can be used new Item. if (!bodyItem.Create(Global.ObjectMgr.GetGenerator(HighGuid.Item).Generate(), 8383, player)) { return; } // in mail template case we need create new item text if (m.mailTemplateId != 0) { MailTemplateRecord mailTemplateEntry = CliDB.MailTemplateStorage.LookupByKey(m.mailTemplateId); if (mailTemplateEntry == null) { player.SendMailResult(packet.MailID, MailResponseType.MadePermanent, MailResponseResult.InternalError); return; } bodyItem.SetText(mailTemplateEntry.Body[GetSessionDbcLocale()]); } else { bodyItem.SetText(m.body); } if (m.messageType == MailMessageType.Normal) { bodyItem.SetGuidValue(ItemFields.Creator, ObjectGuid.Create(HighGuid.Player, m.sender)); } bodyItem.SetFlag(ItemFields.Flags, ItemFieldFlags.Readable); Log.outInfo(LogFilter.Network, "HandleMailCreateTextItem mailid={0}", packet.MailID); List <ItemPosCount> dest = new List <ItemPosCount>(); InventoryResult msg = GetPlayer().CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, dest, bodyItem, false); if (msg == InventoryResult.Ok) { m.checkMask = m.checkMask | MailCheckMask.Copied; m.state = MailState.Changed; player.m_mailsUpdated = true; player.StoreItem(dest, bodyItem, true); player.SendMailResult(packet.MailID, MailResponseType.MadePermanent, MailResponseResult.Ok); } else { player.SendMailResult(packet.MailID, MailResponseType.MadePermanent, MailResponseResult.EquipError, msg); } }
void HandleLootMasterGive(MasterLootItem masterLootItem) { AELootResult aeResult = new(); if (GetPlayer().GetGroup() == null || GetPlayer().GetGroup().GetLooterGuid() != GetPlayer().GetGUID() || GetPlayer().GetGroup().GetLootMethod() != LootMethod.MasterLoot) { GetPlayer().SendLootError(ObjectGuid.Empty, ObjectGuid.Empty, LootError.DidntKill); return; } // player on other map Player target = Global.ObjAccessor.GetPlayer(_player, masterLootItem.Target); if (!target) { GetPlayer().SendLootError(ObjectGuid.Empty, ObjectGuid.Empty, LootError.PlayerNotFound); return; } foreach (LootRequest req in masterLootItem.Loot) { Loot loot = null; ObjectGuid lootguid = _player.GetLootWorldObjectGUID(req.Object); if (!_player.IsInRaidWith(target) || !_player.IsInMap(target)) { _player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterOther); Log.outInfo(LogFilter.Cheat, $"MasterLootItem: Player {GetPlayer().GetName()} tried to give an item to ineligible player {target.GetName()} !"); return; } if (GetPlayer().GetLootGUID().IsCreatureOrVehicle()) { Creature creature = GetPlayer().GetMap().GetCreature(lootguid); if (!creature) { return; } loot = creature.loot; } else if (GetPlayer().GetLootGUID().IsGameObject()) { GameObject pGO = GetPlayer().GetMap().GetGameObject(lootguid); if (!pGO) { return; } loot = pGO.loot; } if (loot == null) { return; } byte slotid = (byte)(req.LootListID - 1); if (slotid >= loot.items.Count + loot.quest_items.Count) { Log.outDebug(LogFilter.Loot, $"MasterLootItem: Player {GetPlayer().GetName()} might be using a hack! (slot {slotid}, size {loot.items.Count})"); return; } LootItem item = slotid >= loot.items.Count ? loot.quest_items[slotid - loot.items.Count] : loot.items[slotid]; List <ItemPosCount> dest = new(); InventoryResult msg = target.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count); if (item.follow_loot_rules && !item.AllowedForPlayer(target)) { msg = InventoryResult.CantEquipEver; } if (msg != InventoryResult.Ok) { if (msg == InventoryResult.ItemMaxCount) { _player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterUniqueItem); } else if (msg == InventoryResult.InvFull) { _player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterInvFull); } else { _player.SendLootError(req.Object, ObjectGuid.Empty, LootError.MasterOther); } target.SendEquipError(msg, null, null, item.itemid); return; } // now move item from loot to target inventory Item newitem = target.StoreNewItem(dest, item.itemid, true, item.randomBonusListId, item.GetAllowedLooters(), item.context, item.BonusListIDs); aeResult.Add(newitem, item.count, loot.loot_type); // mark as looted item.count = 0; item.is_looted = true; loot.NotifyItemRemoved(slotid); --loot.unlootedCount; } foreach (var resultValue in aeResult.GetByOrder()) { target.SendNewItem(resultValue.item, resultValue.count, false, false, true); target.UpdateCriteria(CriteriaTypes.LootItem, resultValue.item.GetEntry(), resultValue.count); target.UpdateCriteria(CriteriaTypes.LootType, resultValue.item.GetEntry(), resultValue.count, (ulong)resultValue.lootType); target.UpdateCriteria(CriteriaTypes.LootEpicItem, resultValue.item.GetEntry(), resultValue.count); } }
public void LoadWardenChecks() { // Check if Warden is enabled by config before loading anything if (!WorldConfig.GetBoolValue(WorldCfg.WardenEnabled)) { Log.outInfo(LogFilter.Warden, "Warden disabled, loading checks skipped."); return; } // 0 1 2 3 4 5 6 7 SQLResult result = DB.World.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 Warden checks. DB table `warden_checks` is empty!"); return; } uint count = 0; do { ushort id = result.Read <ushort>(0); WardenCheckType checkType = (WardenCheckType)result.Read <byte>(1); string data = result.Read <string>(2); string checkResult = result.Read <string>(3); uint address = result.Read <uint>(4); byte length = result.Read <byte>(5); string str = result.Read <string>(6); string comment = result.Read <string>(7); WardenCheck wardenCheck = new WardenCheck(); wardenCheck.Type = checkType; wardenCheck.CheckId = id; // Initialize action with default action from config wardenCheck.Action = (WardenActions)WorldConfig.GetIntValue(WorldCfg.WardenClientFailAction); if (checkType == WardenCheckType.PageA || checkType == WardenCheckType.PageB || checkType == WardenCheckType.Driver) { wardenCheck.Data = new BigInteger(data.ToByteArray()); int len = data.Length / 2; if (wardenCheck.Data.ToByteArray().Length < len) { byte[] temp = wardenCheck.Data.ToByteArray(); Array.Reverse(temp); wardenCheck.Data = new BigInteger(temp); } } if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.Module) { MemChecksIdPool.Add(id); } else { OtherChecksIdPool.Add(id); } if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.PageA || checkType == WardenCheckType.PageB || checkType == WardenCheckType.Proc) { wardenCheck.Address = address; wardenCheck.Length = length; } // PROC_CHECK support missing if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.MPQ || checkType == WardenCheckType.LuaStr || checkType == WardenCheckType.Driver || checkType == WardenCheckType.Module) { wardenCheck.Str = str; } CheckStore[id] = wardenCheck; if (checkType == WardenCheckType.MPQ || checkType == WardenCheckType.Memory) { BigInteger Result = new BigInteger(checkResult.ToByteArray()); int len = checkResult.Length / 2; if (Result.ToByteArray().Length < len) { byte[] temp = Result.ToByteArray(); Array.Reverse(temp); Result = new BigInteger(temp); } CheckResultStore[id] = Result; } if (comment.IsEmpty()) { wardenCheck.Comment = "Undocumented Check"; } else { wardenCheck.Comment = comment; } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} warden checks.", count); }
public void LoadFromDB() { uint count = 0; _maxEventId = 0; _maxInviteId = 0; // 0 1 2 3 4 5 6 7 8 SQLResult result = DB.Characters.Query("SELECT EventID, Owner, Title, Description, EventType, TextureID, Date, Flags, LockDate FROM calendar_events"); if (!result.IsEmpty()) { do { ulong eventID = result.Read <ulong>(0); ObjectGuid ownerGUID = ObjectGuid.Create(HighGuid.Player, result.Read <ulong>(1)); string title = result.Read <string>(2); string description = result.Read <string>(3); CalendarEventType type = (CalendarEventType)result.Read <byte>(4); int textureID = result.Read <int>(5); uint date = result.Read <uint>(6); CalendarFlags flags = (CalendarFlags)result.Read <uint>(7); uint lockDate = result.Read <uint>(8); ulong guildID = 0; if (flags.HasAnyFlag(CalendarFlags.GuildEvent) || flags.HasAnyFlag(CalendarFlags.WithoutInvites)) { guildID = Global.CharacterCacheStorage.GetCharacterGuildIdByGuid(ownerGUID); } CalendarEvent calendarEvent = new CalendarEvent(eventID, ownerGUID, guildID, type, textureID, date, flags, title, description, lockDate); _events.Add(calendarEvent); _maxEventId = Math.Max(_maxEventId, eventID); ++count; }while (result.NextRow()); } Log.outInfo(LogFilter.ServerLoading, "Loaded {0} calendar events", count); count = 0; // 0 1 2 3 4 5 6 7 result = DB.Characters.Query("SELECT InviteID, EventID, Invitee, Sender, Status, ResponseTime, ModerationRank, Note FROM calendar_invites"); if (!result.IsEmpty()) { do { ulong inviteId = result.Read <ulong>(0); ulong eventId = result.Read <ulong>(1); ObjectGuid invitee = ObjectGuid.Create(HighGuid.Player, result.Read <ulong>(2)); ObjectGuid senderGUID = ObjectGuid.Create(HighGuid.Player, result.Read <ulong>(3)); CalendarInviteStatus status = (CalendarInviteStatus)result.Read <byte>(4); uint responseTime = result.Read <uint>(5); CalendarModerationRank rank = (CalendarModerationRank)result.Read <byte>(6); string note = result.Read <string>(7); CalendarInvite invite = new CalendarInvite(inviteId, eventId, invitee, senderGUID, responseTime, status, rank, note); _invites.Add(eventId, invite); _maxInviteId = Math.Max(_maxInviteId, inviteId); ++count; }while (result.NextRow()); } Log.outInfo(LogFilter.ServerLoading, "Loaded {0} calendar invites", count); for (ulong i = 1; i < _maxEventId; ++i) { if (GetEvent(i) == null) { _freeEventIds.Add(i); } } for (ulong i = 1; i < _maxInviteId; ++i) { if (GetInvite(i) == null) { _freeInviteIds.Add(i); } } }