diff options
Diffstat (limited to 'src')
19 files changed, 545 insertions, 396 deletions
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp index e0b1ed3b161..0b9c1b325b7 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/server/collision/Management/MMapManager.cpp @@ -37,11 +37,41 @@ namespace MMAP // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! } + void MMapManager::InitializeThreadUnsafe(const std::vector<uint32>& mapIds) + { + // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime + for (const uint32& mapId : mapIds) + loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); + + thread_safe_environment = false; + } + + MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const + { + // return the iterator if found or end() if not found/NULL + MMapDataSet::const_iterator itr = loadedMMaps.find(mapId); + if (itr != loadedMMaps.cend() && !itr->second) + itr = loadedMMaps.cend(); + + return itr; + } + bool MMapManager::loadMapData(uint32 mapId) { // we already have this map loaded? - if (loadedMMaps.find(mapId) != loadedMMaps.end()) - return true; + MMapDataSet::iterator itr = loadedMMaps.find(mapId); + if (itr != loadedMMaps.end()) + { + if (itr->second) + return true; + } + else + { + if (thread_safe_environment) + itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first; + else + ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); + } // load and init dtNavMesh - read parameters from file std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, sWorld->GetDataPath().c_str(), mapId); @@ -75,7 +105,7 @@ namespace MMAP // store inside our map list MMapData* mmap_data = new MMapData(mesh, mapId); - loadedMMaps.insert(std::pair<uint32, MMapData*>(mapId, mmap_data)); + itr->second = mmap_data; return true; } @@ -252,14 +282,15 @@ namespace MMAP bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) { // check if we have this map loaded - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + MMapDataSet::const_iterator itr = GetMMapData(mapId); + if (itr == loadedMMaps.end()) { // file may not exist, therefore not loaded TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %04u%02i%02i.mmtile", mapId, x, y); return false; } - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = itr->second; // check if we have this tile loaded uint32 packedGridPos = packTileID(x, y); @@ -296,7 +327,8 @@ namespace MMAP bool MMapManager::unloadMap(uint32 mapId) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + MMapDataSet::iterator itr = loadedMMaps.find(mapId); + if (itr == loadedMMaps.end() || !itr->second) { // file may not exist, therefore not loaded TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %04u", mapId); @@ -304,7 +336,7 @@ namespace MMAP } // unload all tiles from given map - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = itr->second; for (MMapTileSet::iterator i = mmap->loadedTileRefs.begin(); i != mmap->loadedTileRefs.end(); ++i) { uint32 x = (i->first >> 16); @@ -320,7 +352,7 @@ namespace MMAP } delete mmap; - loadedMMaps.erase(mapId); + itr->second = nullptr; TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %04i.mmap", mapId); return true; @@ -329,14 +361,15 @@ namespace MMAP bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) { // check if we have this map loaded - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + MMapDataSet::const_iterator itr = GetMMapData(mapId); + if (itr == loadedMMaps.end()) { // file may not exist, therefore not loaded TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %04u", mapId); return false; } - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = itr->second; if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) { TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %04u instanceId %u", mapId, instanceId); @@ -354,18 +387,20 @@ namespace MMAP dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId, TerrainSet swaps) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + MMapDataSet::const_iterator itr = GetMMapData(mapId); + if (itr == loadedMMaps.end()) return NULL; - return loadedMMaps[mapId]->GetNavMesh(swaps); + return itr->second->GetNavMesh(swaps); } dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId, TerrainSet swaps) { - if (loadedMMaps.find(mapId) == loadedMMaps.end()) + MMapDataSet::const_iterator itr = GetMMapData(mapId); + if (itr == loadedMMaps.end()) return NULL; - MMapData* mmap = loadedMMaps[mapId]; + MMapData* mmap = itr->second; if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) { // allocate mesh query diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h index b7356716a9d..2b3818601af 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/server/collision/Management/MMapManager.h @@ -92,9 +92,10 @@ namespace MMAP class MMapManager { public: - MMapManager() : loadedTiles(0) { } + MMapManager() : loadedTiles(0), thread_safe_environment(true) {} ~MMapManager(); + void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId); @@ -115,8 +116,10 @@ namespace MMAP bool loadMapData(uint32 mapId); uint32 packTileID(int32 x, int32 y); + MMapDataSet::const_iterator GetMMapData(uint32 mapId) const; MMapDataSet loadedMMaps; uint32 loadedTiles; + bool thread_safe_environment; PhasedTile* LoadTile(uint32 mapId, int32 x, int32 y); PhaseTileMap _phaseTiles; diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 3ea18f272ae..d98f791421b 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -22,6 +22,7 @@ #include "Define.h" #include "Unit.h" #include "Containers.h" +#include "EventMap.h" #include <list> class Player; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 43ef7d9511b..51769ecdaac 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -28,6 +28,7 @@ #include "GameObject.h" #include "Packets/WorldStatePackets.h" #include "Packets/BattlegroundPackets.h" +#include "EventMap.h" class Creature; class GameObject; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d121e5bb70b..9392f8ab924 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23811,10 +23811,10 @@ void Player::ResurrectUsingRequestData() void Player::SetClientControl(Unit* target, bool allowMove) { - WorldPacket data(SMSG_CONTROL_UPDATE, target->GetPackGUID().size()+1); - data << target->GetPackGUID(); - data << uint8(allowMove ? 1 : 0); - GetSession()->SendPacket(&data); + WorldPackets::Movement::ControlUpdate data; + data.Guid = target->GetGUID(); + data.On = allowMove; + GetSession()->SendPacket(data.Write()); if (this != target) SetViewpoint(target, allowMove); diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 65847ccfa6e..c8c26af2be2 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -680,3 +680,12 @@ void WorldPackets::Movement::SummonResponse::Read() _worldPacket >> SummonerGUID; Accept = _worldPacket.ReadBit(); } + +WorldPacket const* WorldPackets::Movement::ControlUpdate::Write() +{ + _worldPacket << Guid; + _worldPacket.WriteBit(On); + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index 22d1b62a08c..b00d29f5501 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -412,6 +412,17 @@ namespace WorldPackets bool Accept = false; ObjectGuid SummonerGUID; }; + + class ControlUpdate final : public ServerPacket + { + public: + ControlUpdate() : ServerPacket(SMSG_CONTROL_UPDATE, 16 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid Guid; + bool On = false; + }; } ByteBuffer& operator<<(ByteBuffer& data, Movement::MonsterSplineFilterKey const& monsterSplineFilterKey); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 8ab053f2296..38248b9daf6 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1032,7 +1032,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONQUEST_FORMULA_CONSTANTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONSOLE_WRITE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTACT_LIST, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTROL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTROL_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONVERT_RUNE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COOLDOWN_CHEAT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COOLDOWN_EVENT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 027c35dfd7f..372f31d1e97 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -881,6 +881,8 @@ void WorldSocket::SendAuthResponseError(uint8 code) bool WorldSocket::HandlePing(WorldPacket& recvPacket) { + using namespace std::chrono; + uint32 ping; uint32 latency; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 948729c6d70..2fdb8a52aa2 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1471,15 +1471,16 @@ void World::SetInitialWorldSettings() sSpellMgr->LoadPetFamilySpellsStore(); - if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())) - { - std::vector<uint32> mapIds; - for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++) - if (sMapStore.LookupEntry(mapId)) - mapIds.push_back(mapId); + std::vector<uint32> mapIds; + for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++) + if (sMapStore.LookupEntry(mapId)) + mapIds.push_back(mapId); + if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())) vmmgr2->InitializeThreadUnsafe(mapIds); - } + + MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager(); + mmmgr->InitializeThreadUnsafe(mapIds); TC_LOG_INFO("server.loading", "Loading SpellInfo store..."); sSpellMgr->LoadSpellInfoStore(); diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h index 87af9f44eb7..d99476bc7a8 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.h +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h @@ -7,3 +7,4 @@ #include "Errors.h" #include "TypeList.h" #include "TaskScheduler.h" +#include "EventMap.h" diff --git a/src/server/shared/Utilities/Duration.h b/src/server/shared/Utilities/Duration.h new file mode 100644 index 00000000000..58a08e5842f --- /dev/null +++ b/src/server/shared/Utilities/Duration.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _DURATION_H_ +#define _DURATION_H_ + +#include <chrono> + +/// Milliseconds shorthand typedef. +typedef std::chrono::milliseconds Milliseconds; + +/// Seconds shorthand typedef. +typedef std::chrono::seconds Seconds; + +/// Minutes shorthand typedef. +typedef std::chrono::minutes Minutes; + +/// Hours shorthand typedef. +typedef std::chrono::hours Hours; + +/// Makes std::chrono_literals globally available. +// ToDo: Enable this when TC supports C++14. +// using namespace std::chrono_literals; + +#endif // _DURATION_H_ diff --git a/src/server/shared/Utilities/EventMap.cpp b/src/server/shared/Utilities/EventMap.cpp new file mode 100644 index 00000000000..8c3f60afe82 --- /dev/null +++ b/src/server/shared/Utilities/EventMap.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "EventMap.h" + +void EventMap::Reset() +{ + _eventMap.clear(); + _time = 0; + _phase = 0; +} + +void EventMap::SetPhase(uint8 phase) +{ + if (!phase) + _phase = 0; + else if (phase <= 8) + _phase = uint8(1 << (phase - 1)); +} + +void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, uint8 phase /*= 0*/) +{ + if (group && group <= 8) + eventId |= (1 << (group + 15)); + + if (phase && phase <= 8) + eventId |= (1 << (phase + 23)); + + _eventMap.insert(EventStore::value_type(_time + time, eventId)); +} + +uint32 EventMap::ExecuteEvent() +{ + while (!Empty()) + { + EventStore::iterator itr = _eventMap.begin(); + + if (itr->first > _time) + return 0; + else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase)) + _eventMap.erase(itr); + else + { + uint32 eventId = (itr->second & 0x0000FFFF); + _lastEvent = itr->second; // include phase/group + _eventMap.erase(itr); + return eventId; + } + } + + return 0; +} + +void EventMap::DelayEvents(uint32 delay, uint32 group) +{ + if (!group || group > 8 || Empty()) + return; + + EventStore delayed; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (itr->second & (1 << (group + 15))) + { + delayed.insert(EventStore::value_type(itr->first + delay, itr->second)); + _eventMap.erase(itr++); + } + else + ++itr; + } + + _eventMap.insert(delayed.begin(), delayed.end()); +} + +void EventMap::CancelEvent(uint32 eventId) +{ + if (Empty()) + return; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (eventId == (itr->second & 0x0000FFFF)) + _eventMap.erase(itr++); + else + ++itr; + } +} + +void EventMap::CancelEventGroup(uint32 group) +{ + if (!group || group > 8 || Empty()) + return; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (itr->second & (1 << (group + 15))) + _eventMap.erase(itr++); + else + ++itr; + } +} + +uint32 EventMap::GetNextEventTime(uint32 eventId) const +{ + if (Empty()) + return 0; + + for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) + if (eventId == (itr->second & 0x0000FFFF)) + return itr->first; + + return 0; +} + +uint32 EventMap::GetTimeUntilEvent(uint32 eventId) const +{ + for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) + if (eventId == (itr->second & 0x0000FFFF)) + return itr->first - _time; + + return std::numeric_limits<uint32>::max(); +} diff --git a/src/server/shared/Utilities/EventMap.h b/src/server/shared/Utilities/EventMap.h new file mode 100644 index 00000000000..a12cfc0cb4d --- /dev/null +++ b/src/server/shared/Utilities/EventMap.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _EVENT_MAP_H_ +#define _EVENT_MAP_H_ + +#include "Common.h" + +class EventMap +{ + /** + * Internal storage type. + * Key: Time as uint32 when the event should occur. + * Value: The event data as uint32. + * + * Structure of event data: + * - Bit 0 - 15: Event Id. + * - Bit 16 - 23: Group + * - Bit 24 - 31: Phase + * - Pattern: 0xPPGGEEEE + */ + typedef std::multimap<uint32, uint32> EventStore; + +public: + EventMap() : _time(0), _phase(0), _lastEvent(0) { } + + /** + * @name Reset + * @brief Removes all scheduled events and resets time and phase. + */ + void Reset(); + + /** + * @name Update + * @brief Updates the timer of the event map. + * @param time Value to be added to time. + */ + void Update(uint32 time) + { + _time += time; + } + + /** + * @name GetTimer + * @return Current timer value. + */ + uint32 GetTimer() const + { + return _time; + } + + /** + * @name GetPhaseMask + * @return Active phases as mask. + */ + uint8 GetPhaseMask() const + { + return _phase; + } + + /** + * @name Empty + * @return True, if there are no events scheduled. + */ + bool Empty() const + { + return _eventMap.empty(); + } + + /** + * @name SetPhase + * @brief Sets the phase of the map (absolute). + * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase. + */ + void SetPhase(uint8 phase); + + /** + * @name AddPhase + * @brief Activates the given phase (bitwise). + * @param phase Phase which should be activated. Values: 1 - 8 + */ + void AddPhase(uint8 phase) + { + if (phase && phase <= 8) + _phase |= uint8(1 << (phase - 1)); + } + + /** + * @name RemovePhase + * @brief Deactivates the given phase (bitwise). + * @param phase Phase which should be deactivated. Values: 1 - 8. + */ + void RemovePhase(uint8 phase) + { + if (phase && phase <= 8) + _phase &= uint8(~(1 << (phase - 1))); + } + + /** + * @name ScheduleEvent + * @brief Creates new event entry in map. + * @param eventId The id of the new event. + * @param time The time in milliseconds until the event occurs. + * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. + * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. + */ + void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0); + + /** + * @name RescheduleEvent + * @brief Cancels the given event and reschedules it. + * @param eventId The id of the event. + * @param time The time in milliseconds until the event occurs. + * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. + * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. + */ + void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) + { + CancelEvent(eventId); + ScheduleEvent(eventId, time, group, phase); + } + + /** + * @name RepeatEvent + * @brief Repeats the mostly recently executed event. + * @param time Time until the event occurs. + */ + void Repeat(uint32 time) + { + _eventMap.insert(EventStore::value_type(_time + time, _lastEvent)); + } + + /** + * @name RepeatEvent + * @brief Repeats the mostly recently executed event, Equivalent to Repeat(urand(minTime, maxTime). + * @param minTime Minimum time until the event occurs. + * @param maxTime Maximum time until the event occurs. + */ + void Repeat(uint32 minTime, uint32 maxTime) + { + Repeat(urand(minTime, maxTime)); + } + + /** + * @name ExecuteEvent + * @brief Returns the next event to execute and removes it from map. + * @return Id of the event to execute. + */ + uint32 ExecuteEvent(); + + /** + * @name DelayEvents + * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. + * @param delay Amount of delay. + */ + void DelayEvents(uint32 delay) + { + _time = delay < _time ? _time - delay : 0; + } + + /** + * @name DelayEvents + * @brief Delay all events of the same group. + * @param delay Amount of delay. + * @param group Group of the events. + */ + void DelayEvents(uint32 delay, uint32 group); + + /** + * @name CancelEvent + * @brief Cancels all events of the specified id. + * @param eventId Event id to cancel. + */ + void CancelEvent(uint32 eventId); + + /** + * @name CancelEventGroup + * @brief Cancel events belonging to specified group. + * @param group Group to cancel. + */ + void CancelEventGroup(uint32 group); + + /** + * @name GetNextEventTime + * @brief Returns closest occurence of specified event. + * @param eventId Wanted event id. + * @return Time of found event. + */ + uint32 GetNextEventTime(uint32 eventId) const; + + /** + * @name GetNextEventTime + * @return Time of next event. + */ + uint32 GetNextEventTime() const + { + return Empty() ? 0 : _eventMap.begin()->first; + } + + /** + * @name IsInPhase + * @brief Returns whether event map is in specified phase or not. + * @param phase Wanted phase. + * @return True, if phase of event map contains specified phase. + */ + bool IsInPhase(uint8 phase) const + { + return phase <= 8 && (!phase || _phase & (1 << (phase - 1))); + } + + /** + * @name GetTimeUntilEvent + * @brief Returns time in milliseconds until next event. + * @param eventId of the event. + * @return Time of next event. + */ + uint32 GetTimeUntilEvent(uint32 eventId) const; + +private: + /** + * @name _time + * @brief Internal timer. + * + * This does not represent the real date/time value. + * It's more like a stopwatch: It can run, it can be stopped, + * it can be resetted and so on. Events occur when this timer + * has reached their time value. Its value is changed in the + * Update method. + */ + uint32 _time; + + /** + * @name _phase + * @brief Phase mask of the event map. + * + * Contains the phases the event map is in. Multiple + * phases from 1 to 8 can be set with SetPhase or + * AddPhase. RemovePhase deactives a phase. + */ + uint8 _phase; + + /** + * @name _eventMap + * @brief Internal event storage map. Contains the scheduled events. + * + * See typedef at the beginning of the class for more + * details. + */ + EventStore _eventMap; + + /** + * @name _lastEvent + * @brief Stores information on the most recently executed event + */ + uint32 _lastEvent; +}; + +#endif // _EVENT_MAP_H_ diff --git a/src/server/shared/Utilities/StringFormat.h b/src/server/shared/Utilities/StringFormat.h index 70d9aefb14d..0e9dde471da 100644 --- a/src/server/shared/Utilities/StringFormat.h +++ b/src/server/shared/Utilities/StringFormat.h @@ -23,11 +23,11 @@ namespace Trinity { - //! Default TC string format function - template<typename... Args> - inline std::string StringFormat(const char* fmt, Args const&... args) + /// Default TC string format function. + template<typename Format, typename... Args> + inline std::string StringFormat(Format&& fmt, Args&&... args) { - return fmt::sprintf(fmt, args...); + return fmt::sprintf(std::forward<Format>(fmt), std::forward<Args>(args)...); } } diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h index d45835b5f17..f1fe7ea0a21 100644 --- a/src/server/shared/Utilities/TaskScheduler.h +++ b/src/server/shared/Utilities/TaskScheduler.h @@ -29,6 +29,7 @@ #include <boost/optional.hpp> #include "Util.h" +#include "Duration.h" class TaskContext; @@ -646,16 +647,4 @@ private: void Invoke(); }; -/// Milliseconds shorthand typedef. -typedef std::chrono::milliseconds Milliseconds; - -/// Seconds shorthand typedef. -typedef std::chrono::seconds Seconds; - -/// Minutes shorthand typedef. -typedef std::chrono::minutes Minutes; - -/// Hours shorthand typedef. -typedef std::chrono::hours Hours; - #endif /// _TASK_SCHEDULER_H_ diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h index b7d2fa1b5ad..c54903d7be2 100644 --- a/src/server/shared/Utilities/Timer.h +++ b/src/server/shared/Utilities/Timer.h @@ -21,10 +21,10 @@ #include <chrono> -using namespace std::chrono; - inline uint32 getMSTime() { + using namespace std::chrono; + static const system_clock::time_point ApplicationStartTime = system_clock::now(); return uint32(duration_cast<milliseconds>(system_clock::now() - ApplicationStartTime).count()); diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index 9a3d612a54b..ec67968f11e 100644 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -573,15 +573,6 @@ std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse return ss.str(); } -uint32 EventMap::GetTimeUntilEvent(uint32 eventId) const -{ - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first - _time; - - return std::numeric_limits<uint32>::max(); -} - void HexStrToByteArray(std::string const& str, uint8* out, bool reverse /*= false*/) { // string must have even number of characters diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index 9605efe18ec..a96fd21058f 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -555,346 +555,4 @@ bool CompareValues(ComparisionType type, T val1, T val2) } } -class EventMap -{ - /** - * Internal storage type. - * Key: Time as uint32 when the event should occur. - * Value: The event data as uint32. - * - * Structure of event data: - * - Bit 0 - 15: Event Id. - * - Bit 16 - 23: Group - * - Bit 24 - 31: Phase - * - Pattern: 0xPPGGEEEE - */ - typedef std::multimap<uint32, uint32> EventStore; - - public: - EventMap() : _time(0), _phase(0), _lastEvent(0) { } - - /** - * @name Reset - * @brief Removes all scheduled events and resets time and phase. - */ - void Reset() - { - _eventMap.clear(); - _time = 0; - _phase = 0; - } - - /** - * @name Update - * @brief Updates the timer of the event map. - * @param time Value to be added to time. - */ - void Update(uint32 time) - { - _time += time; - } - - /** - * @name GetTimer - * @return Current timer value. - */ - uint32 GetTimer() const - { - return _time; - } - - /** - * @name GetPhaseMask - * @return Active phases as mask. - */ - uint8 GetPhaseMask() const - { - return _phase; - } - - /** - * @name Empty - * @return True, if there are no events scheduled. - */ - bool Empty() const - { - return _eventMap.empty(); - } - - /** - * @name SetPhase - * @brief Sets the phase of the map (absolute). - * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase. - */ - void SetPhase(uint8 phase) - { - if (!phase) - _phase = 0; - else if (phase <= 8) - _phase = uint8(1 << (phase - 1)); - } - - /** - * @name AddPhase - * @brief Activates the given phase (bitwise). - * @param phase Phase which should be activated. Values: 1 - 8 - */ - void AddPhase(uint8 phase) - { - if (phase && phase <= 8) - _phase |= uint8(1 << (phase - 1)); - } - - /** - * @name RemovePhase - * @brief Deactivates the given phase (bitwise). - * @param phase Phase which should be deactivated. Values: 1 - 8. - */ - void RemovePhase(uint8 phase) - { - if (phase && phase <= 8) - _phase &= uint8(~(1 << (phase - 1))); - } - - /** - * @name ScheduleEvent - * @brief Creates new event entry in map. - * @param eventId The id of the new event. - * @param time The time in milliseconds until the event occurs. - * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. - * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. - */ - void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) - { - if (group && group <= 8) - eventId |= (1 << (group + 15)); - - if (phase && phase <= 8) - eventId |= (1 << (phase + 23)); - - _eventMap.insert(EventStore::value_type(_time + time, eventId)); - } - - /** - * @name RescheduleEvent - * @brief Cancels the given event and reschedules it. - * @param eventId The id of the event. - * @param time The time in milliseconds until the event occurs. - * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. - * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. - */ - void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) - { - CancelEvent(eventId); - ScheduleEvent(eventId, time, group, phase); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param time Time until the event occurs. - */ - void Repeat(uint32 time) - { - _eventMap.insert(EventStore::value_type(_time + time, _lastEvent)); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event, Equivalent to Repeat(urand(minTime, maxTime). - * @param minTime Minimum time until the event occurs. - * @param maxTime Maximum time until the event occurs. - */ - void Repeat(uint32 minTime, uint32 maxTime) - { - Repeat(urand(minTime, maxTime)); - } - - /** - * @name ExecuteEvent - * @brief Returns the next event to execute and removes it from map. - * @return Id of the event to execute. - */ - uint32 ExecuteEvent() - { - while (!Empty()) - { - EventStore::iterator itr = _eventMap.begin(); - - if (itr->first > _time) - return 0; - else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase)) - _eventMap.erase(itr); - else - { - uint32 eventId = (itr->second & 0x0000FFFF); - _lastEvent = itr->second; // include phase/group - _eventMap.erase(itr); - return eventId; - } - } - - return 0; - } - - /** - * @name DelayEvents - * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. - * @param delay Amount of delay. - */ - void DelayEvents(uint32 delay) - { - _time = delay < _time ? _time - delay : 0; - } - - /** - * @name DelayEvents - * @brief Delay all events of the same group. - * @param delay Amount of delay. - * @param group Group of the events. - */ - void DelayEvents(uint32 delay, uint32 group) - { - if (!group || group > 8 || Empty()) - return; - - EventStore delayed; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - { - delayed.insert(EventStore::value_type(itr->first + delay, itr->second)); - _eventMap.erase(itr++); - } - else - ++itr; - } - - _eventMap.insert(delayed.begin(), delayed.end()); - } - - /** - * @name CancelEvent - * @brief Cancels all events of the specified id. - * @param eventId Event id to cancel. - */ - void CancelEvent(uint32 eventId) - { - if (Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (eventId == (itr->second & 0x0000FFFF)) - _eventMap.erase(itr++); - else - ++itr; - } - } - - /** - * @name CancelEventGroup - * @brief Cancel events belonging to specified group. - * @param group Group to cancel. - */ - void CancelEventGroup(uint32 group) - { - if (!group || group > 8 || Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - _eventMap.erase(itr++); - else - ++itr; - } - } - - /** - * @name GetNextEventTime - * @brief Returns closest occurence of specified event. - * @param eventId Wanted event id. - * @return Time of found event. - */ - uint32 GetNextEventTime(uint32 eventId) const - { - if (Empty()) - return 0; - - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first; - - return 0; - } - - /** - * @name GetNextEventTime - * @return Time of next event. - */ - uint32 GetNextEventTime() const - { - return Empty() ? 0 : _eventMap.begin()->first; - } - - /** - * @name IsInPhase - * @brief Returns wether event map is in specified phase or not. - * @param phase Wanted phase. - * @return True, if phase of event map contains specified phase. - */ - bool IsInPhase(uint8 phase) - { - return phase <= 8 && (!phase || _phase & (1 << (phase - 1))); - } - - /** - * @name GetTimeUntilEvent - * @brief Returns time in milliseconds until next event. - * @param eventId of the event. - * @return Time of next event. - */ - uint32 GetTimeUntilEvent(uint32 eventId) const; - - private: - /** - * @name _time - * @brief Internal timer. - * - * This does not represent the real date/time value. - * It's more like a stopwatch: It can run, it can be stopped, - * it can be resetted and so on. Events occur when this timer - * has reached their time value. Its value is changed in the - * Update method. - */ - uint32 _time; - - /** - * @name _phase - * @brief Phase mask of the event map. - * - * Contains the phases the event map is in. Multiple - * phases from 1 to 8 can be set with SetPhase or - * AddPhase. RemovePhase deactives a phase. - */ - uint8 _phase; - - /** - * @name _eventMap - * @brief Internal event storage map. Contains the scheduled events. - * - * See typedef at the beginning of the class for more - * details. - */ - EventStore _eventMap; - - /** - * @name _lastEvent - * @brief Stores information on the most recently executed event - */ - uint32 _lastEvent; -}; - #endif |