Fixed weather updates to be thread safe

This commit is contained in:
hondacrx
2017-09-20 00:27:47 -04:00
parent 28e6d6870a
commit 1b9bf99d8c
6 changed files with 88 additions and 103 deletions
+1 -4
View File
@@ -1276,10 +1276,7 @@ namespace Game.Chat
Player player = handler.GetSession().GetPlayer(); Player player = handler.GetSession().GetPlayer();
uint zoneid = player.GetZoneId(); uint zoneid = player.GetZoneId();
Weather weather = Global.WeatherMgr.FindWeather(zoneid); Weather weather = player.GetMap().GetOrGenerateZoneDefaultWeather(zoneid);
if (weather == null)
weather = Global.WeatherMgr.AddWeather(zoneid);
if (weather == null) if (weather == null)
{ {
handler.SendSysMessage(CypherStrings.NoWeather); handler.SendSysMessage(CypherStrings.NoWeather);
+3 -11
View File
@@ -175,18 +175,10 @@ namespace Game.Entities
if (zone == null) if (zone == null)
return; return;
if (WorldConfig.GetBoolValue(WorldCfg.Weather) && !HasAuraType(AuraType.ForceWeather)) if (WorldConfig.GetBoolValue(WorldCfg.Weather))
{ GetMap().GetOrGenerateZoneDefaultWeather(newZone);
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);
}
}
GetMap().SendZoneDynamicInfo(newZone, this);
Global.ScriptMgr.OnPlayerUpdateZone(this, newZone, newArea); Global.ScriptMgr.OnPlayerUpdateZone(this, newZone, newArea);
+72 -14
View File
@@ -64,6 +64,8 @@ namespace Game.Maps
//lets initialize visibility distance for map //lets initialize visibility distance for map
InitVisibilityDistance(); InitVisibilityDistance();
_weatherUpdateTimer = new IntervalTimer();
_weatherUpdateTimer.SetInterval(1 * Time.InMilliseconds);
GetGuidSequenceGenerator(HighGuid.Transport).Set(Global.ObjectMgr.GetGenerator(HighGuid.Transport).GetNextAfterMaxUsed()); GetGuidSequenceGenerator(HighGuid.Transport).Set(Global.ObjectMgr.GetGenerator(HighGuid.Transport).GetNextAfterMaxUsed());
@@ -407,7 +409,6 @@ namespace Game.Maps
SendInitSelf(player); SendInitSelf(player);
SendInitTransports(player); SendInitTransports(player);
SendZoneDynamicInfo(player);
if (initPlayer) if (initPlayer)
player.m_clientGUIDs.Clear(); player.m_clientGUIDs.Clear();
@@ -635,6 +636,17 @@ namespace Game.Maps
i_scriptLock = false; 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(); MoveAllCreaturesInMoveList();
MoveAllGameObjectsInMoveList(); MoveAllGameObjectsInMoveList();
MoveAllAreaTriggersInMoveList(); 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); var zoneInfo = _zoneDynamicInfo.LookupByKey(zoneId);
if (zoneInfo == null) if (zoneInfo == null)
return; return;
@@ -2622,12 +2633,7 @@ namespace Game.Maps
if (music != 0) if (music != 0)
player.SendPacket(new PlayMusic(music)); player.SendPacket(new PlayMusic(music));
WeatherState weatherId = zoneInfo.WeatherId; SendZoneWeather(zoneInfo, player);
if (weatherId != 0)
{
WeatherPkt weather = new WeatherPkt(weatherId, zoneInfo.WeatherGrade);
player.SendPacket(weather);
}
uint overrideLightId = zoneInfo.OverrideLightId; uint overrideLightId = zoneInfo.OverrideLightId;
if (overrideLightId != 0) 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) public void SetZoneMusic(uint zoneId, uint musicId)
{ {
if (!_zoneDynamicInfo.ContainsKey(zoneId)) if (!_zoneDynamicInfo.ContainsKey(zoneId))
@@ -2650,14 +2684,34 @@ namespace Game.Maps
var players = GetPlayers(); var players = GetPlayers();
if (!players.Empty()) if (!players.Empty())
{ {
PlayMusic data = new PlayMusic(musicId); PlayMusic playMusic = new PlayMusic(musicId);
foreach (var player in players) foreach (var player in players)
if (player.GetZoneId() == zoneId) if (player.GetZoneId() == zoneId && !player.HasAuraType(AuraType.ForceWeather))
player.SendPacket(data); 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) void SetZoneWeather(uint zoneId, WeatherState weatherId, float weatherGrade)
{ {
if (!_zoneDynamicInfo.ContainsKey(zoneId)) if (!_zoneDynamicInfo.ContainsKey(zoneId))
@@ -2666,17 +2720,19 @@ namespace Game.Maps
ZoneDynamicInfo info = _zoneDynamicInfo[zoneId]; ZoneDynamicInfo info = _zoneDynamicInfo[zoneId];
info.WeatherId = weatherId; info.WeatherId = weatherId;
info.WeatherGrade = weatherGrade; info.WeatherGrade = weatherGrade;
var players = GetPlayers();
var players = GetPlayers();
if (!players.Empty()) if (!players.Empty())
{ {
WeatherPkt weather = new WeatherPkt(weatherId, weatherGrade); WeatherPkt weather = new WeatherPkt(weatherId, weatherGrade);
foreach (var player in players) foreach (var player in players)
{
if (player.GetZoneId() == zoneId) if (player.GetZoneId() == zoneId)
player.SendPacket(weather); player.SendPacket(weather);
} }
} }
}
void SetZoneOverrideLight(uint zoneId, uint lightId, uint fadeInTime) void SetZoneOverrideLight(uint zoneId, uint lightId, uint fadeInTime)
{ {
@@ -4157,6 +4213,7 @@ namespace Game.Maps
internal uint m_unloadTimer; internal uint m_unloadTimer;
Dictionary<uint, ZoneDynamicInfo> _zoneDynamicInfo = new Dictionary<uint, ZoneDynamicInfo>(); Dictionary<uint, ZoneDynamicInfo> _zoneDynamicInfo = new Dictionary<uint, ZoneDynamicInfo>();
IntervalTimer _weatherUpdateTimer;
uint _defaultLight; uint _defaultLight;
Dictionary<HighGuid, ObjectGuidGenerator> _guidGenerators = new Dictionary<HighGuid, ObjectGuidGenerator>(); Dictionary<HighGuid, ObjectGuidGenerator> _guidGenerators = new Dictionary<HighGuid, ObjectGuidGenerator>();
Dictionary<ObjectGuid, WorldObject> _objectsStore = new Dictionary<ObjectGuid, WorldObject>(); Dictionary<ObjectGuid, WorldObject> _objectsStore = new Dictionary<ObjectGuid, WorldObject>();
@@ -4698,7 +4755,8 @@ namespace Game.Maps
public class ZoneDynamicInfo public class ZoneDynamicInfo
{ {
public uint MusicId; public uint MusicId;
public WeatherState WeatherId = WeatherState.Fine; public Weather DefaultWeather;
public WeatherState WeatherId;
public float WeatherGrade; public float WeatherGrade;
public uint OverrideLightId; public uint OverrideLightId;
public uint LightFadeInTime; public uint LightFadeInTime;
-9
View File
@@ -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 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.Auctions].SetInterval(Time.Minute * Time.InMilliseconds);
m_timers[WorldTimers.AuctionsPending].SetInterval(250); m_timers[WorldTimers.AuctionsPending].SetInterval(250);
@@ -1222,13 +1221,6 @@ namespace Game
UpdateSessions(diff); UpdateSessions(diff);
RecordTimeDiff("UpdateSessions"); 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());
}
/// <li> Update uptime table /// <li> Update uptime table
if (m_timers[WorldTimers.UpTime].Passed()) if (m_timers[WorldTimers.UpTime].Passed())
{ {
@@ -2446,7 +2438,6 @@ namespace Game
{ {
Auctions, Auctions,
AuctionsPending, AuctionsPending,
Weathers,
UpTime, UpTime,
Corpses, Corpses,
Events, Events,
+2 -18
View File
@@ -6093,25 +6093,9 @@ namespace Game.Spells
return; return;
if (apply) if (apply)
{ target.SendPacket(new WeatherPkt((WeatherState)GetMiscValue(), 1.0f));
WeatherPkt weather = new WeatherPkt((WeatherState)GetMiscValue(), 1.0f);
target.SendPacket(weather);
}
else else
{ target.GetMap().SendZoneWeather(target.GetZoneId(), target);
// 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);
}
}
}
} }
[AuraEffectHandler(AuraType.EnableAltPower)] [AuraEffectHandler(AuraType.EnableAltPower)]
+9 -46
View File
@@ -27,32 +27,6 @@ namespace Game
{ {
WeatherManager() { } 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() public void LoadWeatherData()
{ {
uint oldMSTime = Time.GetMSTime(); uint oldMSTime = Time.GetMSTime();
@@ -101,7 +75,7 @@ namespace Game
} }
wzc.ScriptId = Global.ObjectMgr.GetScriptId(result.Read<string>(13)); wzc.ScriptId = Global.ObjectMgr.GetScriptId(result.Read<string>(13));
mWeatherZoneMap[zone_id] = wzc; _weatherData[zone_id] = wzc;
++count; ++count;
} }
while (result.NextRow()); while (result.NextRow());
@@ -109,28 +83,12 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} weather definitions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); 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); return _weatherData.LookupByKey(zone_id);
player.SendPacket(weather);
} }
public void Update(uint diff) Dictionary<uint, WeatherData> _weatherData = new Dictionary<uint, WeatherData>();
{
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<uint, Weather> m_weathers = new Dictionary<uint, Weather>();
Dictionary<uint, WeatherData> mWeatherZoneMap = new Dictionary<uint, WeatherData>();
} }
public class Weather public class Weather
@@ -296,6 +254,11 @@ namespace Game
player.SendPacket(weather); player.SendPacket(weather);
} }
public static void SendFineWeatherUpdateToPlayer(Player player)
{
player.SendPacket(new WeatherPkt(WeatherState.Fine));
}
public bool UpdateWeather() public bool UpdateWeather()
{ {
Player player = Global.WorldMgr.FindPlayerInZone(m_zone); Player player = Global.WorldMgr.FindPlayerInZone(m_zone);