aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2017-09-14 22:33:40 +0200
committerShauren <shauren.trinity@gmail.com>2017-09-14 22:33:40 +0200
commit6eb997394722fcd4b5248646b5abfa185a7ec58f (patch)
treed6a224a43940a1ba0580450854dcf55399222fc1
parent6d2bc7abf48a7e64b04b42b082ebabecd0c5dce6 (diff)
Core/Weather: Fixed weather updates to be thread safe
-rw-r--r--src/server/game/Entities/Player/Player.cpp12
-rw-r--r--src/server/game/Maps/Map.cpp93
-rw-r--r--src/server/game/Maps/Map.h8
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp19
-rw-r--r--src/server/game/Weather/Weather.cpp18
-rw-r--r--src/server/game/Weather/Weather.h1
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp74
-rw-r--r--src/server/game/Weather/WeatherMgr.h10
-rw-r--r--src/server/game/World/World.cpp8
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp5
11 files changed, 103 insertions, 146 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index abfe384e0f2..0f19eb40455 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7022,14 +7022,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea)
if (!zone)
return;
- if (sWorld->getBoolConfig(CONFIG_WEATHER) && !HasAuraType(SPELL_AURA_FORCE_WEATHER))
- {
- if (Weather* weather = WeatherMgr::FindWeather(newZone))
- weather->SendWeatherUpdateToPlayer(this);
- else if (!WeatherMgr::AddWeather(newZone))
- // send fine weather packet to remove old zone's weather
- WeatherMgr::SendFineWeatherUpdateToPlayer(this);
- }
+ if (sWorld->getBoolConfig(CONFIG_WEATHER))
+ GetMap()->GetOrGenerateZoneDefaultWeather(newZone);
+
+ GetMap()->SendZoneDynamicInfo(newZone, this);
sScriptMgr->OnPlayerUpdateZone(this, newZone, newArea);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 23fceaa36fc..d174f756ba3 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -46,6 +46,7 @@
#include "Vehicle.h"
#include "VMapFactory.h"
#include "Weather.h"
+#include "WeatherMgr.h"
#include "World.h"
#include "WorldSession.h"
@@ -62,7 +63,7 @@ u_map_magic MapLiquidMagic = { {'M','L','I','Q'} };
GridState* si_GridStates[MAX_GRID_STATE];
-ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), WeatherId(WEATHER_STATE_FINE),
+ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), DefaultWeather(nullptr), WeatherId(WEATHER_STATE_FINE),
WeatherGrade(0.0f), OverrideLightId(0), LightFadeInTime(0) { }
Map::~Map()
@@ -264,6 +265,8 @@ i_scriptLock(false), _defaultLight(DB2Manager::GetDefaultMapLight(id))
//lets initialize visibility distance for map
Map::InitVisibilityDistance();
+ _weatherUpdateTimer.SetInterval(time_t(1 * IN_MILLISECONDS));
+
GetGuidSequenceGenerator<HighGuid::Transport>().Set(sObjectMgr->GetGenerator<HighGuid::Transport>().GetNextAfterMaxUsed());
sScriptMgr->OnCreateMap(this);
@@ -560,7 +563,6 @@ bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
SendInitSelf(player);
SendInitTransports(player);
- SendZoneDynamicInfo(player);
if (initPlayer)
player->m_clientGUIDs.clear();
@@ -808,6 +810,15 @@ void Map::Update(const uint32 t_diff)
i_scriptLock = false;
}
+ if (_weatherUpdateTimer.Passed())
+ {
+ for (auto&& zoneInfo : _zoneDynamicInfo)
+ if (zoneInfo.second.DefaultWeather && !zoneInfo.second.DefaultWeather->Update(_weatherUpdateTimer.GetInterval()))
+ zoneInfo.second.DefaultWeather.reset();
+
+ _weatherUpdateTimer.Reset();
+ }
+
MoveAllCreaturesInMoveList();
MoveAllGameObjectsInMoveList();
MoveAllAreaTriggersInMoveList();
@@ -4140,21 +4151,16 @@ void Map::RemoveOldCorpses()
}
}
-void Map::SendZoneDynamicInfo(Player* player)
+void Map::SendZoneDynamicInfo(uint32 zoneId, Player* player) const
{
- uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
- ZoneDynamicInfoMap::const_iterator itr = _zoneDynamicInfo.find(zoneId);
+ auto itr = _zoneDynamicInfo.find(zoneId);
if (itr == _zoneDynamicInfo.end())
return;
if (uint32 music = itr->second.MusicId)
player->SendDirectMessage(WorldPackets::Misc::PlayMusic(music).Write());
- if (WeatherState weatherId = itr->second.WeatherId)
- {
- WorldPackets::Misc::Weather weather(weatherId, itr->second.WeatherGrade);
- player->SendDirectMessage(weather.Write());
- }
+ SendZoneWeather(itr->second, player);
if (uint32 overrideLightId = itr->second.OverrideLightId)
{
@@ -4166,54 +4172,93 @@ void Map::SendZoneDynamicInfo(Player* player)
}
}
-void Map::SetZoneMusic(uint32 zoneId, uint32 musicId)
+void Map::SendZoneWeather(uint32 zoneId, Player* player) const
{
- if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
- _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
+ if (!player->HasAuraType(SPELL_AURA_FORCE_WEATHER))
+ {
+ auto itr = _zoneDynamicInfo.find(zoneId);
+ if (itr == _zoneDynamicInfo.end())
+ return;
+
+ SendZoneWeather(itr->second, player);
+ }
+}
+
+void Map::SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const
+{
+ if (WeatherState weatherId = zoneDynamicInfo.WeatherId)
+ {
+ WorldPackets::Misc::Weather weather(weatherId, zoneDynamicInfo.WeatherGrade);
+ player->SendDirectMessage(weather.Write());
+ }
+ else if (zoneDynamicInfo.DefaultWeather)
+ {
+ zoneDynamicInfo.DefaultWeather->SendWeatherUpdateToPlayer(player);
+ }
+ else
+ Weather::SendFineWeatherUpdateToPlayer(player);
+}
+void Map::SetZoneMusic(uint32 zoneId, uint32 musicId)
+{
_zoneDynamicInfo[zoneId].MusicId = musicId;
Map::PlayerList const& players = GetPlayers();
if (!players.isEmpty())
{
+ WorldPackets::Misc::PlayMusic playMusic(musicId);
+ playMusic.Write();
+
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
- if (player->GetZoneId() == zoneId)
- player->SendDirectMessage(WorldPackets::Misc::PlayMusic(musicId).Write());
+ if (player->GetZoneId() == zoneId && !player->HasAuraType(SPELL_AURA_FORCE_WEATHER))
+ player->SendDirectMessage(playMusic.GetRawPacket());
}
}
-void Map::SetZoneWeather(uint32 zoneId, WeatherState weatherId, float weatherGrade)
+Weather* Map::GetOrGenerateZoneDefaultWeather(uint32 zoneId)
{
- if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
- _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
+ WeatherData const* weatherData = WeatherMgr::GetWeatherData(zoneId);
+ if (!weatherData)
+ return nullptr;
ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
+ if (!info.DefaultWeather)
+ {
+ info.DefaultWeather = Trinity::make_unique<Weather>(zoneId, weatherData);
+ info.DefaultWeather->ReGenerate();
+ info.DefaultWeather->UpdateWeather();
+ }
+
+ return info.DefaultWeather.get();
+}
+
+void Map::SetZoneWeather(uint32 zoneId, WeatherState weatherId, float weatherGrade)
+{
+ ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
info.WeatherId = weatherId;
info.WeatherGrade = weatherGrade;
- Map::PlayerList const& players = GetPlayers();
+ Map::PlayerList const& players = GetPlayers();
if (!players.isEmpty())
{
WorldPackets::Misc::Weather weather(weatherId, weatherGrade);
+ weather.Write();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
if (Player* player = itr->GetSource())
if (player->GetZoneId() == zoneId)
- player->SendDirectMessage(weather.Write());
+ player->SendDirectMessage(weather.GetRawPacket());
}
}
void Map::SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime)
{
- if (_zoneDynamicInfo.find(zoneId) == _zoneDynamicInfo.end())
- _zoneDynamicInfo.insert(ZoneDynamicInfoMap::value_type(zoneId, ZoneDynamicInfo()));
-
ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
info.OverrideLightId = lightId;
info.LightFadeInTime = fadeInTime;
- Map::PlayerList const& players = GetPlayers();
+ Map::PlayerList const& players = GetPlayers();
if (!players.isEmpty())
{
WorldPackets::Misc::OverrideLight overrideLight;
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 69dfd6affba..67edd41fd48 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -51,6 +51,7 @@ class Object;
class Player;
class TempSummon;
class Unit;
+class Weather;
class WorldObject;
class WorldPacket;
struct MapDifficultyEntry;
@@ -231,6 +232,7 @@ struct ZoneDynamicInfo
ZoneDynamicInfo();
uint32 MusicId;
+ std::unique_ptr<Weather> DefaultWeather;
WeatherState WeatherId;
float WeatherGrade;
uint32 OverrideLightId;
@@ -536,9 +538,12 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
void SendInitTransports(Player* player);
void SendRemoveTransports(Player* player);
void SendUpdateTransportVisibility(Player* player, std::set<uint32> const& previousPhases);
- void SendZoneDynamicInfo(Player* player);
+ void SendZoneDynamicInfo(uint32 zoneId, Player* player) const;
+ void SendZoneWeather(uint32 zoneId, Player* player) const;
+ void SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const;
void SetZoneMusic(uint32 zoneId, uint32 musicId);
+ Weather* GetOrGenerateZoneDefaultWeather(uint32 zoneId);
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float weatherGrade);
void SetZoneOverrideLight(uint32 zoneId, uint32 lightId, uint32 fadeInTime);
@@ -715,6 +720,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
std::unordered_map<ObjectGuid::LowType /*dbGUID*/, time_t> _goRespawnTimes;
ZoneDynamicInfoMap _zoneDynamicInfo;
+ IntervalTimer _weatherUpdateTimer;
uint32 _defaultLight;
template<HighGuid high>
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index b45c3cb985a..4328b051623 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -6333,24 +6333,9 @@ void AuraEffect::HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mod
return;
if (apply)
- {
- WorldPackets::Misc::Weather weather(WeatherState(GetMiscValue()), 1.0f);
- target->SendDirectMessage(weather.Write());
- }
+ target->SendDirectMessage(WorldPackets::Misc::Weather(WeatherState(GetMiscValue()), 1.0f).Write());
else
- {
- // send weather for current zone
- if (Weather* weather = WeatherMgr::FindWeather(target->GetZoneId()))
- weather->SendWeatherUpdateToPlayer(target);
- else
- {
- if (!WeatherMgr::AddWeather(target->GetZoneId()))
- {
- // send fine weather packet to remove old weather
- WeatherMgr::SendFineWeatherUpdateToPlayer(target);
- }
- }
- }
+ target->GetMap()->SendZoneWeather(target->GetZoneId(), target);
}
void AuraEffect::HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index 37be7e40e85..9494dfe9e56 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -21,15 +21,13 @@
*/
#include "Weather.h"
-#include "WorldPacket.h"
-#include "Player.h"
-#include "World.h"
#include "Log.h"
-#include "Util.h"
-#include "ScriptMgr.h"
-#include "WorldSession.h"
#include "MiscPackets.h"
+#include "Player.h"
#include "Random.h"
+#include "ScriptMgr.h"
+#include "Util.h"
+#include "World.h"
/// Create the Weather object
Weather::Weather(uint32 zone, WeatherData const* weatherChances)
@@ -195,7 +193,13 @@ bool Weather::ReGenerate()
void Weather::SendWeatherUpdateToPlayer(Player* player)
{
WorldPackets::Misc::Weather weather(GetWeatherState(), m_grade);
- player->GetSession()->SendPacket(weather.Write());
+ player->SendDirectMessage(weather.Write());
+}
+
+void Weather::SendFineWeatherUpdateToPlayer(Player* player)
+{
+ WorldPackets::Misc::Weather weather(WEATHER_STATE_FINE);
+ player->SendDirectMessage(weather.Write());
}
/// Send the new weather to all players in the zone
diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h
index da1e5b13af3..e38ecc9a612 100644
--- a/src/server/game/Weather/Weather.h
+++ b/src/server/game/Weather/Weather.h
@@ -74,6 +74,7 @@ class TC_GAME_API Weather
bool UpdateWeather();
void SendWeatherUpdateToPlayer(Player* player);
+ static void SendFineWeatherUpdateToPlayer(Player* player);
void SetWeather(WeatherType type, float grade);
/// For which zone is this weather?
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index fcda5662560..ae69d8a009f 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -21,64 +21,24 @@
*/
#include "WeatherMgr.h"
+#include "Containers.h"
#include "DatabaseEnv.h"
#include "Log.h"
-#include "MiscPackets.h"
#include "ObjectMgr.h"
-#include "Player.h"
+#include "Timer.h"
#include "Weather.h"
-#include "WorldSession.h"
namespace WeatherMgr
{
namespace
{
- typedef std::unordered_map<uint32, std::shared_ptr<Weather> > WeatherMap;
- typedef std::unordered_map<uint32, WeatherData> WeatherZoneMap;
-
- WeatherMap m_weathers;
- WeatherZoneMap mWeatherZoneMap;
-
- WeatherData const* GetWeatherData(uint32 zone_id)
- {
- WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id);
- return (itr != mWeatherZoneMap.end()) ? &itr->second : NULL;
- }
-}
-
-/// Find a Weather object by the given zoneid
-Weather* FindWeather(uint32 id)
-{
- WeatherMap::const_iterator itr = m_weathers.find(id);
- return (itr != m_weathers.end()) ? itr->second.get() : nullptr;
+ std::unordered_map<uint32, WeatherData> _weatherData;
}
-/// Remove a Weather object for the given zoneid
-void RemoveWeather(uint32 id)
+WeatherData const* GetWeatherData(uint32 zone_id)
{
- // not called at the moment. Kept for completeness
- WeatherMap::iterator itr = m_weathers.find(id);
-
- if (itr != m_weathers.end())
- m_weathers.erase(itr);
-}
-
-/// Add a Weather object to the list
-Weather* AddWeather(uint32 zone_id)
-{
- WeatherData const* weatherChances = GetWeatherData(zone_id);
-
- // zone does not have weather, ignore
- if (!weatherChances)
- return NULL;
-
- Weather* w = new Weather(zone_id, weatherChances);
- m_weathers[w->GetZone()].reset(w);
- w->ReGenerate();
- w->UpdateWeather();
-
- return w;
+ return Trinity::Containers::MapGetValuePtr(_weatherData, zone_id);
}
void LoadWeatherData()
@@ -106,7 +66,7 @@ void LoadWeatherData()
uint32 zone_id = fields[0].GetUInt32();
- WeatherData& wzc = mWeatherZoneMap[zone_id];
+ WeatherData& wzc = _weatherData[zone_id];
for (uint8 season = 0; season < WEATHER_SEASONS; ++season)
{
@@ -142,26 +102,4 @@ void LoadWeatherData()
TC_LOG_INFO("server.loading", ">> Loaded %u weather definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
-void SendFineWeatherUpdateToPlayer(Player* player)
-{
- WorldPackets::Misc::Weather weather(WEATHER_STATE_FINE);
- player->GetSession()->SendPacket(weather.Write());
-}
-
-void Update(uint32 diff)
-{
- ///- Send an update signal to Weather objects
- WeatherMap::iterator itr, next;
- for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next)
- {
- next = itr;
- ++next;
-
- ///- and remove Weather objects for zones with no player
- // As interval > WorldTick
- if (!itr->second->Update(diff))
- m_weathers.erase(itr);
- }
-}
-
} // namespace
diff --git a/src/server/game/Weather/WeatherMgr.h b/src/server/game/Weather/WeatherMgr.h
index e00f190b0dc..155f04c64d5 100644
--- a/src/server/game/Weather/WeatherMgr.h
+++ b/src/server/game/Weather/WeatherMgr.h
@@ -27,18 +27,12 @@
class Weather;
class Player;
+struct WeatherData;
namespace WeatherMgr
{
TC_GAME_API void LoadWeatherData();
-
- TC_GAME_API Weather* FindWeather(uint32 id);
- TC_GAME_API Weather* AddWeather(uint32 zone_id);
- TC_GAME_API void RemoveWeather(uint32 zone_id);
-
- TC_GAME_API void SendFineWeatherUpdateToPlayer(Player* player);
-
- TC_GAME_API void Update(uint32 diff);
+ TC_GAME_API WeatherData const* GetWeatherData(uint32 zone_id);
}
#endif
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 96fd5f02905..8014ee90347 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2059,7 +2059,6 @@ void World::SetInitialWorldSettings()
LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')",
realm.Id.Realm, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query
- m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS);
m_timers[WUPDATE_AUCTIONS_PENDING].SetInterval(250);
m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS);
@@ -2377,13 +2376,6 @@ void World::Update(uint32 diff)
UpdateSessions(diff);
RecordTimeDiff("UpdateSessions");
- /// <li> Handle weather updates when the timer has passed
- if (m_timers[WUPDATE_WEATHERS].Passed())
- {
- m_timers[WUPDATE_WEATHERS].Reset();
- WeatherMgr::Update(uint32(m_timers[WUPDATE_WEATHERS].GetInterval()));
- }
-
/// <li> Update uptime table
if (m_timers[WUPDATE_UPTIME].Passed())
{
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index e48df5d3e82..b390c2e074d 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -81,7 +81,6 @@ enum WorldTimers
{
WUPDATE_AUCTIONS,
WUPDATE_AUCTIONS_PENDING,
- WUPDATE_WEATHERS,
WUPDATE_UPTIME,
WUPDATE_CORPSES,
WUPDATE_EVENTS,
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 7249a1ebb30..eff5e5049f7 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -1496,10 +1496,7 @@ public:
Player* player = handler->GetSession()->GetPlayer();
uint32 zoneid = player->GetZoneId();
- Weather* weather = WeatherMgr::FindWeather(zoneid);
-
- if (!weather)
- weather = WeatherMgr::AddWeather(zoneid);
+ Weather* weather = player->GetMap()->GetOrGenerateZoneDefaultWeather(zoneid);
if (!weather)
{
handler->SendSysMessage(LANG_NO_WEATHER);