diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-09-14 22:33:40 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-09-14 22:33:40 +0200 |
commit | 6eb997394722fcd4b5248646b5abfa185a7ec58f (patch) | |
tree | d6a224a43940a1ba0580450854dcf55399222fc1 | |
parent | 6d2bc7abf48a7e64b04b42b082ebabecd0c5dce6 (diff) |
Core/Weather: Fixed weather updates to be thread safe
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 93 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 8 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 19 | ||||
-rw-r--r-- | src/server/game/Weather/Weather.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Weather/Weather.h | 1 | ||||
-rw-r--r-- | src/server/game/Weather/WeatherMgr.cpp | 74 | ||||
-rw-r--r-- | src/server/game/Weather/WeatherMgr.h | 10 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 8 | ||||
-rw-r--r-- | src/server/game/World/World.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 5 |
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); |