diff --git a/Source/Game/DataStorage/WhoListStorage.cs b/Source/Game/DataStorage/WhoListStorage.cs new file mode 100644 index 000000000..911c9c299 --- /dev/null +++ b/Source/Game/DataStorage/WhoListStorage.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Framework.Constants; +using Game.Entities; +using Game.Guilds; + +namespace Game.DataStorage +{ + public class WhoListPlayerInfo + { + public WhoListPlayerInfo(ObjectGuid guid, Team team, AccountTypes security, uint level, Class clss, Race race, uint zoneid, byte gender, bool visible, bool gamemaster, string playerName, string guildName, ObjectGuid guildguid) + { + Guid = guid; + Team = team; + Security = security; + Level = level; + Class = (byte)clss; + Race = (byte)race; + ZoneId = zoneid; + Gender = gender; + IsVisible = visible; + IsGamemaster = gamemaster; + PlayerName = playerName; + GuildName = guildName; + GuildGuid = guildguid; + } + + public ObjectGuid Guid { get; } + public Team Team { get; } + public AccountTypes Security { get; } + public uint Level { get; } + public byte Class { get; } + public byte Race { get; } + public uint ZoneId { get; } + public byte Gender { get; } + public bool IsVisible { get; } + public bool IsGamemaster { get; } + public string PlayerName { get; } + public string GuildName { get; } + public ObjectGuid GuildGuid { get; } + } + + public class WhoListStorageManager : Singleton + { + List _whoListStorage; + + WhoListStorageManager() + { + _whoListStorage = new List(); + } + + public void Update() + { + // clear current list + _whoListStorage.Clear(); + + var players = Global.ObjAccessor.GetPlayers(); + foreach (var player in players) + { + if (player.GetMap() == null || player.GetSession().PlayerLoading()) + continue; + + string playerName = player.GetName(); + string guildName = Global.GuildMgr.GetGuildNameById((uint)player.GetGuildId()); + + Guild guild = player.GetGuild(); + ObjectGuid guildGuid = ObjectGuid.Empty; + + if (guild) + guildGuid = guild.GetGUID(); + + _whoListStorage.Add(new WhoListPlayerInfo(player.GetGUID(), player.GetTeam(), player.GetSession().GetSecurity(), player.getLevel(), + player.GetClass(), player.GetRace(), player.GetZoneId(), player.m_playerData.NativeSex, player.IsVisible(), + player.IsGameMaster(), playerName, guildName, guildGuid)); + } + } + + public List GetWhoList() { return _whoListStorage; } + } +} diff --git a/Source/Game/Globals/Global.cs b/Source/Game/Globals/Global.cs index 724c6d33a..4a4abebbe 100644 --- a/Source/Game/Globals/Global.cs +++ b/Source/Game/Globals/Global.cs @@ -52,6 +52,7 @@ public static class Global //Social public static CalendarManager CalendarMgr { get { return CalendarManager.Instance; } } public static SocialManager SocialMgr { get { return SocialManager.Instance; } } + public static WhoListStorageManager WhoListStorageMgr { get { return WhoListStorageManager.Instance; } } //Scripts public static ScriptManager ScriptMgr { get { return ScriptManager.Instance; } } diff --git a/Source/Game/Handlers/SocialHandler.cs b/Source/Game/Handlers/SocialHandler.cs index 218aca768..a87ba4587 100644 --- a/Source/Game/Handlers/SocialHandler.cs +++ b/Source/Game/Handlers/SocialHandler.cs @@ -29,7 +29,7 @@ namespace Game { public partial class WorldSession { - [WorldPacketHandler(ClientOpcodes.Who)] + [WorldPacketHandler(ClientOpcodes.Who, Processing = PacketProcessing.ThreadSafe)] void HandleWho(WhoRequestPkt whoRequest) { WhoRequest request = whoRequest.Request; @@ -66,61 +66,53 @@ namespace Game uint gmLevelInWhoList = WorldConfig.GetUIntValue(WorldCfg.GmLevelInWhoList); WhoResponsePkt response = new WhoResponsePkt(); - foreach (var target in Global.ObjAccessor.GetPlayers()) + List whoList = Global.WhoListStorageMgr.GetWhoList(); + foreach (WhoListPlayerInfo target in whoList) { // player can see member of other team only if CONFIG_ALLOW_TWO_SIDE_WHO_LIST - if (target.GetTeam() != team && !HasPermission(RBACPermissions.TwoSideWhoList)) + if (target.Team != team && !HasPermission(RBACPermissions.TwoSideWhoList)) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST - if (target.GetSession().GetSecurity() > (AccountTypes)gmLevelInWhoList && !HasPermission(RBACPermissions.WhoSeeAllSecLevels)) - continue; - - // do not process players which are not in world - if (!target.IsInWorld) + if (target.Security > (AccountTypes)gmLevelInWhoList && !HasPermission(RBACPermissions.WhoSeeAllSecLevels)) continue; // check if target is globally visible for player - if (!target.IsVisibleGloballyFor(GetPlayer())) - continue; + if (_player.GetGUID() != target.Guid && !target.IsVisible) + if (Global.AccountMgr.IsPlayerAccount(_player.GetSession().GetSecurity()) || target.Security > _player.GetSession().GetSecurity()) + continue; // check if target's level is in level range - uint lvl = target.getLevel(); + uint lvl = target.Level; if (lvl < request.MinLevel || lvl > request.MaxLevel) continue; // check if class matches classmask - int class_ = (byte)target.GetClass(); - if (!Convert.ToBoolean(request.ClassFilter & (1 << class_))) + if (!Convert.ToBoolean(request.ClassFilter & (1 << target.Class))) continue; // check if race matches racemask - int race = (int)target.GetRace(); - if (!Convert.ToBoolean(request.RaceFilter & (1 << race))) + if (!Convert.ToBoolean(request.RaceFilter & (1 << target.Race))) continue; if (!whoRequest.Areas.Empty()) { - if (whoRequest.Areas.Contains((int)target.GetZoneId())) + if (whoRequest.Areas.Contains((int)target.ZoneId)) continue; } - string wTargetName = target.GetName().ToLower(); - if (!string.IsNullOrEmpty(request.Name) && !wTargetName.Equals(request.Name)) + string wTargetName = target.PlayerName.ToLower(); + if (!(request.Name.IsEmpty() || wTargetName.Equals(request.Name))) continue; - string wTargetGuildName = ""; - Guild targetGuild = target.GetGuild(); - if (targetGuild) - wTargetGuildName = targetGuild.GetName().ToLower(); - - if (!string.IsNullOrEmpty(request.Guild) && !wTargetGuildName.Equals(request.Guild)) + string wTargetGuildName = target.GuildName.ToLower(); + if (!request.Guild.IsEmpty() && !wTargetGuildName.Equals(request.Guild)) continue; if (!request.Words.Empty()) { string aname = ""; - AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(target.GetZoneId()); + AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(target.ZoneId); if (areaEntry != null) aname = areaEntry.AreaName[GetSessionDbcLocale()].ToLower(); @@ -144,18 +136,18 @@ namespace Game } WhoEntry whoEntry = new WhoEntry(); - if (!whoEntry.PlayerData.Initialize(target.GetGUID(), target)) + if (!whoEntry.PlayerData.Initialize(target.Guid, null)) continue; - if (targetGuild) + if (!target.GuildGuid.IsEmpty()) { - whoEntry.GuildGUID = targetGuild.GetGUID(); + whoEntry.GuildGUID = target.GuildGuid; whoEntry.GuildVirtualRealmAddress = Global.WorldMgr.GetVirtualRealmAddress(); - whoEntry.GuildName = targetGuild.GetName(); + whoEntry.GuildName = target.GuildName; } - whoEntry.AreaID = (int)target.GetZoneId(); - whoEntry.IsGM = target.IsGameMaster(); + whoEntry.AreaID = (int)target.ZoneId; + whoEntry.IsGM = target.IsGamemaster; response.Response.Add(whoEntry); diff --git a/Source/Game/Server/WorldManager.cs b/Source/Game/Server/WorldManager.cs index 2d1110415..58d1834ff 100644 --- a/Source/Game/Server/WorldManager.cs +++ b/Source/Game/Server/WorldManager.cs @@ -858,6 +858,8 @@ namespace Game blackmarket_timer = 0; + m_timers[WorldTimers.WhoList].SetInterval(5 * Time.InMilliseconds); // update who list cache every 5 seconds + //to set mailtimer to return mails every day between 4 and 5 am //mailtimer is increased when updating auctions //one second is 1000 -(tested on win system) @@ -1161,6 +1163,14 @@ namespace Game m_timers[i].SetCurrent(0); } + // Update Who List Storage + if (m_timers[WorldTimers.WhoList].Passed()) + { + m_timers[WorldTimers.WhoList].Reset(); + Global.WhoListStorageMgr.Update(); + } + + // Update the game time and check for shutdown time _UpdateGameTime(); // Handle daily quests reset time @@ -2473,6 +2483,7 @@ namespace Game PingDB, GuildSave, Blackmarket, + WhoList, Max }