diff --git a/src/game/Maps/Map.cpp b/src/game/Maps/Map.cpp index 2b4372d0f16..070491ba4be 100644 --- a/src/game/Maps/Map.cpp +++ b/src/game/Maps/Map.cpp @@ -821,9 +821,12 @@ inline void Map::UpdateCells(uint32 map_diff) { uint32 now = WorldTimer::getMSTime(); uint32 diff = WorldTimer::getMSTimeDiff(_lastCellsUpdate, now); + if (diff < sWorld.getConfig(CONFIG_UINT32_MAPUPDATE_UPDATE_CELLS_DIFF)) return; + _lastCellsUpdate = now; + m_currentTime = std::chrono::time_point_cast(Clock::now()); // update active cells around players and active objects if (IsContinent() && m_cellThreads->status() == ThreadPool::Status::READY) @@ -846,22 +849,27 @@ inline void Map::UpdateCells(uint32 map_diff) void Map::ProcessSessionPackets(PacketProcessing type) { - uint32 beginTime = WorldTimer::getMSTime(); + TimePoint beginTime = std::chrono::time_point_cast(Clock::now()); + // update worldsessions for existing players for (m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter) { Player* plr = m_mapRefIter->getSource(); if (plr && plr->IsInWorld()) { + if (type == PACKET_PROCESS_SPELLS) + plr->UpdateCooldowns(beginTime); + WorldSession* pSession = plr->GetSession(); MapSessionFilter updater(pSession); updater.SetProcessType(type); pSession->ProcessPackets(updater); } } - beginTime = WorldTimer::getMSTimeDiffToNow(beginTime); - if (sWorld.getConfig(CONFIG_UINT32_PERFLOG_SLOW_MAP_PACKETS) && beginTime > sWorld.getConfig(CONFIG_UINT32_PERFLOG_SLOW_MAP_PACKETS)) - sLog.Out(LOG_PERFORMANCE, LOG_LVL_BASIC, "Map %u inst %u: %3ums to update packets type %u", GetId(), GetInstanceId(), beginTime, type); + + auto elapsedTime = std::chrono::time_point_cast(Clock::now()) - beginTime; + if (sWorld.getConfig(CONFIG_UINT32_PERFLOG_SLOW_MAP_PACKETS) && elapsedTime.count() > sWorld.getConfig(CONFIG_UINT32_PERFLOG_SLOW_MAP_PACKETS)) + sLog.Out(LOG_PERFORMANCE, LOG_LVL_BASIC, "Map %u inst %u: %3ums to update packets type %u", GetId(), GetInstanceId(), elapsedTime.count(), type); } void Map::UpdateSessionsMovementAndSpellsIfNeeded() @@ -885,6 +893,8 @@ void Map::UpdatePlayers() if (diff < sWorld.getConfig(CONFIG_UINT32_MAPUPDATE_UPDATE_PLAYERS_DIFF)) return; + m_currentTime = std::chrono::time_point_cast(Clock::now()); + ++_inactivePlayersSkippedUpdates; bool updateInactivePlayers = _inactivePlayersSkippedUpdates > sWorld.getConfig(CONFIG_UINT32_INACTIVE_PLAYERS_SKIP_UPDATES); if (!IsContinent()) @@ -923,6 +933,7 @@ void Map::DoUpdate(uint32 maxDiff) void Map::Update(uint32 t_diff) { uint32 updateMapTime = WorldTimer::getMSTime(); + m_currentTime = std::chrono::time_point_cast(Clock::now()); _dynamicTree.update(t_diff); UpdateSessionsMovementAndSpellsIfNeeded(); diff --git a/src/game/Maps/Map.h b/src/game/Maps/Map.h index b2f46366858..28e57209cf5 100644 --- a/src/game/Maps/Map.h +++ b/src/game/Maps/Map.h @@ -575,6 +575,7 @@ class Map : public GridRefManager void MarkNotUpdated() { m_updateFinished = false; } void SetUpdateDiffMod(int32 d) { m_updateDiffMod = d; } uint32 GetUpdateDiffMod() const { return m_updateDiffMod; } + TimePoint GetCurrentClockTime() const { return m_currentTime; } void BindToInstanceOrRaid(Player* player, time_t objectResetTime, bool permBindToRaid); // WeatherSystem @@ -697,6 +698,7 @@ class Map : public GridRefManager bool m_crashed = false; bool m_updateFinished = false; uint32 m_updateDiffMod; + TimePoint m_currentTime; uint32 m_lastMvtSpellsUpdate = 0; private: time_t i_gridExpiry; diff --git a/src/game/Objects/GameObject.cpp b/src/game/Objects/GameObject.cpp index 724e4015919..95a425d774d 100644 --- a/src/game/Objects/GameObject.cpp +++ b/src/game/Objects/GameObject.cpp @@ -318,7 +318,7 @@ void GameObject::Update(uint32 update_diff, uint32 /*p_time*/) return; } - UpdateCooldowns(sWorld.GetCurrentClockTime()); + UpdateCooldowns(GetMap()->GetCurrentClockTime()); m_Events.Update(update_diff); diff --git a/src/game/Objects/Player.cpp b/src/game/Objects/Player.cpp index 795fc8d1fd4..472ba141f38 100644 --- a/src/game/Objects/Player.cpp +++ b/src/game/Objects/Player.cpp @@ -22397,12 +22397,14 @@ void Player::AddGCD(SpellEntry const& spellEntry, uint32 /*forcedDuration = 0*/, gcdDuration = std::min(gcdDuration, 1500); } - if (!gcdDuration) + if (gcdDuration < 1) return; - // TODO: Remove this once spells are queuable and GCD is checked on execute - gcdDuration -= std::min(300, GetSession()->GetLatency()); - gcdDuration -= std::min(200, sWorld.GetCurrentDiff()); + // Spell packets are handled on Map update to substract the update interval. + gcdDuration -= int32(sWorld.getConfig(CONFIG_UINT32_INTERVAL_MAPUPDATE)); + + if (gcdDuration < 1) + gcdDuration = 1; SpellCaster::AddGCD(spellEntry, gcdDuration); diff --git a/src/game/Objects/SpellCaster.h b/src/game/Objects/SpellCaster.h index 0e6fde6d245..866ad564f8c 100644 --- a/src/game/Objects/SpellCaster.h +++ b/src/game/Objects/SpellCaster.h @@ -423,6 +423,7 @@ class SpellCaster : public WorldObject virtual void LockOutSpells(SpellSchoolMask schoolMask, uint32 duration); void PrintCooldownList(ChatHandler& chat) const; bool CheckLockout(SpellSchoolMask schoolMask) const; + void UpdateCooldowns(TimePoint const& now); // Event handler EventProcessor m_Events; @@ -430,7 +431,6 @@ class SpellCaster : public WorldObject explicit SpellCaster() = default; // cooldown system - void UpdateCooldowns(TimePoint const& now); bool GetExpireTime(SpellEntry const& spellEntry, TimePoint& expireTime, bool& isPermanent) const; GCDMap m_GCDCatMap; diff --git a/src/game/Objects/Unit.cpp b/src/game/Objects/Unit.cpp index b6a602750fd..159408d6769 100644 --- a/src/game/Objects/Unit.cpp +++ b/src/game/Objects/Unit.cpp @@ -212,7 +212,7 @@ void Unit::Update(uint32 update_diff, uint32 p_time) // Buffer spell system update time to save on performance when players are updated twice per // world update. We do not need to update spells when the interval is only a few ms (~10ms) - UpdateCooldowns(sWorld.GetCurrentClockTime()); + UpdateCooldowns(GetMap()->GetCurrentClockTime()); m_spellUpdateTimeBuffer += update_diff; if (m_spellUpdateTimeBuffer >= UNIT_SPELL_UPDATE_TIME_BUFFER) {