From 1b9bf99d8cda863d95cb8fa091ff77830ba04929 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 20 Sep 2017 00:27:47 -0400 Subject: [PATCH] Fixed weather updates to be thread safe --- Game/Chat/Commands/MiscCommands.cs | 5 +- Game/Entities/Player/Player.Map.cs | 14 +---- Game/Maps/Map.cs | 88 +++++++++++++++++++++++++----- Game/Server/WorldManager.cs | 9 --- Game/Spells/Auras/AuraEffect.cs | 20 +------ Game/Weather/WeatherManager.cs | 55 +++---------------- 6 files changed, 88 insertions(+), 103 deletions(-) diff --git a/Game/Chat/Commands/MiscCommands.cs b/Game/Chat/Commands/MiscCommands.cs index f6ecedeb6..044853d70 100644 --- a/Game/Chat/Commands/MiscCommands.cs +++ b/Game/Chat/Commands/MiscCommands.cs @@ -1276,10 +1276,7 @@ namespace Game.Chat Player player = handler.GetSession().GetPlayer(); uint zoneid = player.GetZoneId(); - Weather weather = Global.WeatherMgr.FindWeather(zoneid); - - if (weather == null) - weather = Global.WeatherMgr.AddWeather(zoneid); + Weather weather = player.GetMap().GetOrGenerateZoneDefaultWeather(zoneid); if (weather == null) { handler.SendSysMessage(CypherStrings.NoWeather); diff --git a/Game/Entities/Player/Player.Map.cs b/Game/Entities/Player/Player.Map.cs index 49e3ea3c8..ea6109a63 100644 --- a/Game/Entities/Player/Player.Map.cs +++ b/Game/Entities/Player/Player.Map.cs @@ -175,18 +175,10 @@ namespace Game.Entities if (zone == null) return; - if (WorldConfig.GetBoolValue(WorldCfg.Weather) && !HasAuraType(AuraType.ForceWeather)) - { - Weather weather = Global.WeatherMgr.FindWeather(newZone); - if (weather != null) - weather.SendWeatherUpdateToPlayer(this); - else if (Global.WeatherMgr.AddWeather(newZone) == null) - { - // send fine weather packet to remove old zone's weather - Global.WeatherMgr.SendFineWeatherUpdateToPlayer(this); - } - } + if (WorldConfig.GetBoolValue(WorldCfg.Weather)) + GetMap().GetOrGenerateZoneDefaultWeather(newZone); + GetMap().SendZoneDynamicInfo(newZone, this); Global.ScriptMgr.OnPlayerUpdateZone(this, newZone, newArea); diff --git a/Game/Maps/Map.cs b/Game/Maps/Map.cs index 997e0416b..5ff3d0b08 100644 --- a/Game/Maps/Map.cs +++ b/Game/Maps/Map.cs @@ -64,6 +64,8 @@ namespace Game.Maps //lets initialize visibility distance for map InitVisibilityDistance(); + _weatherUpdateTimer = new IntervalTimer(); + _weatherUpdateTimer.SetInterval(1 * Time.InMilliseconds); GetGuidSequenceGenerator(HighGuid.Transport).Set(Global.ObjectMgr.GetGenerator(HighGuid.Transport).GetNextAfterMaxUsed()); @@ -407,7 +409,6 @@ namespace Game.Maps SendInitSelf(player); SendInitTransports(player); - SendZoneDynamicInfo(player); if (initPlayer) player.m_clientGUIDs.Clear(); @@ -634,7 +635,18 @@ namespace Game.Maps ScriptsProcess(); i_scriptLock = false; } - + + if (_weatherUpdateTimer.Passed()) + { + foreach (var zoneInfo in _zoneDynamicInfo) + { + if (zoneInfo.Value.DefaultWeather != null && !zoneInfo.Value.DefaultWeather.Update((uint)_weatherUpdateTimer.GetInterval())) + zoneInfo.Value.DefaultWeather = null; + } + + _weatherUpdateTimer.Reset(); + } + MoveAllCreaturesInMoveList(); MoveAllGameObjectsInMoveList(); MoveAllAreaTriggersInMoveList(); @@ -2611,9 +2623,8 @@ namespace Game.Maps } } - void SendZoneDynamicInfo(Player player) + public void SendZoneDynamicInfo(uint zoneId, Player player) { - uint zoneId = GetZoneId(player.GetPositionX(), player.GetPositionY(), player.GetPositionZ()); var zoneInfo = _zoneDynamicInfo.LookupByKey(zoneId); if (zoneInfo == null) return; @@ -2622,12 +2633,7 @@ namespace Game.Maps if (music != 0) player.SendPacket(new PlayMusic(music)); - WeatherState weatherId = zoneInfo.WeatherId; - if (weatherId != 0) - { - WeatherPkt weather = new WeatherPkt(weatherId, zoneInfo.WeatherGrade); - player.SendPacket(weather); - } + SendZoneWeather(zoneInfo, player); uint overrideLightId = zoneInfo.OverrideLightId; if (overrideLightId != 0) @@ -2640,6 +2646,34 @@ namespace Game.Maps } } + public void SendZoneWeather(uint zoneId, Player player) + { + if (!player.HasAuraType(AuraType.ForceWeather)) + { + var zoneInfo = _zoneDynamicInfo.LookupByKey(zoneId); + if (zoneInfo == null) + return; + + SendZoneWeather(zoneInfo, player); + } + } + + void SendZoneWeather(ZoneDynamicInfo zoneDynamicInfo, Player player) + { + WeatherState weatherId = zoneDynamicInfo.WeatherId; + if (weatherId != 0) + { + WeatherPkt weather = new WeatherPkt(weatherId, zoneDynamicInfo.WeatherGrade); + player.SendPacket(weather); + } + else if (zoneDynamicInfo.DefaultWeather != null) + { + zoneDynamicInfo.DefaultWeather.SendWeatherUpdateToPlayer(player); + } + else + Weather.SendFineWeatherUpdateToPlayer(player); + } + public void SetZoneMusic(uint zoneId, uint musicId) { if (!_zoneDynamicInfo.ContainsKey(zoneId)) @@ -2650,14 +2684,34 @@ namespace Game.Maps var players = GetPlayers(); if (!players.Empty()) { - PlayMusic data = new PlayMusic(musicId); + PlayMusic playMusic = new PlayMusic(musicId); foreach (var player in players) - if (player.GetZoneId() == zoneId) - player.SendPacket(data); + if (player.GetZoneId() == zoneId && !player.HasAuraType(AuraType.ForceWeather)) + player.SendPacket(playMusic); } } + public Weather GetOrGenerateZoneDefaultWeather(uint zoneId) + { + WeatherData weatherData = Global.WeatherMgr.GetWeatherData(zoneId); + if (weatherData == null) + return null; + + if (!_zoneDynamicInfo.ContainsKey(zoneId)) + _zoneDynamicInfo[zoneId] = new ZoneDynamicInfo(); + + ZoneDynamicInfo info = _zoneDynamicInfo[zoneId]; + if (info.DefaultWeather == null) + { + info.DefaultWeather = new Weather(zoneId, weatherData); + info.DefaultWeather.ReGenerate(); + info.DefaultWeather.UpdateWeather(); + } + + return info.DefaultWeather; + } + void SetZoneWeather(uint zoneId, WeatherState weatherId, float weatherGrade) { if (!_zoneDynamicInfo.ContainsKey(zoneId)) @@ -2666,15 +2720,17 @@ namespace Game.Maps ZoneDynamicInfo info = _zoneDynamicInfo[zoneId]; info.WeatherId = weatherId; info.WeatherGrade = weatherGrade; - var players = GetPlayers(); + var players = GetPlayers(); if (!players.Empty()) { WeatherPkt weather = new WeatherPkt(weatherId, weatherGrade); foreach (var player in players) + { if (player.GetZoneId() == zoneId) player.SendPacket(weather); + } } } @@ -4157,6 +4213,7 @@ namespace Game.Maps internal uint m_unloadTimer; Dictionary _zoneDynamicInfo = new Dictionary(); + IntervalTimer _weatherUpdateTimer; uint _defaultLight; Dictionary _guidGenerators = new Dictionary(); Dictionary _objectsStore = new Dictionary(); @@ -4698,7 +4755,8 @@ namespace Game.Maps public class ZoneDynamicInfo { public uint MusicId; - public WeatherState WeatherId = WeatherState.Fine; + public Weather DefaultWeather; + public WeatherState WeatherId; public float WeatherGrade; public uint OverrideLightId; public uint LightFadeInTime; diff --git a/Game/Server/WorldManager.cs b/Game/Server/WorldManager.cs index c2c567da5..cf4a50e19 100644 --- a/Game/Server/WorldManager.cs +++ b/Game/Server/WorldManager.cs @@ -824,7 +824,6 @@ namespace Game DB.Login.Execute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES({0}, {1}, 0, '{2}')", _realm.Id.Realm, m_startTime, ""); // One-time query - m_timers[WorldTimers.Weathers].SetInterval(1 * Time.InMilliseconds); m_timers[WorldTimers.Auctions].SetInterval(Time.Minute * Time.InMilliseconds); m_timers[WorldTimers.AuctionsPending].SetInterval(250); @@ -1222,13 +1221,6 @@ namespace Game UpdateSessions(diff); RecordTimeDiff("UpdateSessions"); - //Handle weather updates when the timer has passed - if (m_timers[WorldTimers.Weathers].Passed()) - { - m_timers[WorldTimers.Weathers].Reset(); - Global.WeatherMgr.Update((uint)m_timers[WorldTimers.Weathers].GetInterval()); - } - ///
  • Update uptime table if (m_timers[WorldTimers.UpTime].Passed()) { @@ -2446,7 +2438,6 @@ namespace Game { Auctions, AuctionsPending, - Weathers, UpTime, Corpses, Events, diff --git a/Game/Spells/Auras/AuraEffect.cs b/Game/Spells/Auras/AuraEffect.cs index b52c5e074..4bf061ba8 100644 --- a/Game/Spells/Auras/AuraEffect.cs +++ b/Game/Spells/Auras/AuraEffect.cs @@ -6093,25 +6093,9 @@ namespace Game.Spells return; if (apply) - { - WeatherPkt weather = new WeatherPkt((WeatherState)GetMiscValue(), 1.0f); - target.SendPacket(weather); - } + target.SendPacket(new WeatherPkt((WeatherState)GetMiscValue(), 1.0f)); else - { - // send weather for current zone - Weather weather = Global.WeatherMgr.FindWeather(target.GetZoneId()); - if (weather != null) - weather.SendWeatherUpdateToPlayer(target); - else - { - if (Global.WeatherMgr.AddWeather(target.GetZoneId()) == null) - { - // send fine weather packet to remove old weather - Global.WeatherMgr.SendFineWeatherUpdateToPlayer(target); - } - } - } + target.GetMap().SendZoneWeather(target.GetZoneId(), target); } [AuraEffectHandler(AuraType.EnableAltPower)] diff --git a/Game/Weather/WeatherManager.cs b/Game/Weather/WeatherManager.cs index d87445ff9..605bcd142 100644 --- a/Game/Weather/WeatherManager.cs +++ b/Game/Weather/WeatherManager.cs @@ -27,32 +27,6 @@ namespace Game { WeatherManager() { } - /// Find a Weather object by the given zoneid - public Weather FindWeather(uint id) - { - return m_weathers.LookupByKey(id); - } - - void RemoveWeather(uint id) - { - m_weathers.Remove(id); - } - - public Weather AddWeather(uint zone_id) - { - WeatherData weatherChances = GetWeatherData(zone_id); - - // zone does not have weather, ignore - if (weatherChances == null) - return null; - - Weather w = new Weather(zone_id, weatherChances); - w.ReGenerate(); - w.UpdateWeather(); - - return w; - } - public void LoadWeatherData() { uint oldMSTime = Time.GetMSTime(); @@ -101,7 +75,7 @@ namespace Game } wzc.ScriptId = Global.ObjectMgr.GetScriptId(result.Read(13)); - mWeatherZoneMap[zone_id] = wzc; + _weatherData[zone_id] = wzc; ++count; } while (result.NextRow()); @@ -109,28 +83,12 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loaded {0} weather definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } - public void SendFineWeatherUpdateToPlayer(Player player) + public WeatherData GetWeatherData(uint zone_id) { - WeatherPkt weather = new WeatherPkt(WeatherState.Fine); - player.SendPacket(weather); + return _weatherData.LookupByKey(zone_id); } - public void Update(uint diff) - { - foreach (var pair in m_weathers.ToList()) - { - if (!pair.Value.Update(diff)) - m_weathers.Remove(pair.Key); - } - } - - WeatherData GetWeatherData(uint zone_id) - { - return mWeatherZoneMap.LookupByKey(zone_id); - } - - Dictionary m_weathers = new Dictionary(); - Dictionary mWeatherZoneMap = new Dictionary(); + Dictionary _weatherData = new Dictionary(); } public class Weather @@ -296,6 +254,11 @@ namespace Game player.SendPacket(weather); } + public static void SendFineWeatherUpdateToPlayer(Player player) + { + player.SendPacket(new WeatherPkt(WeatherState.Fine)); + } + public bool UpdateWeather() { Player player = Global.WorldMgr.FindPlayerInZone(m_zone);