Internal Timer Rewrite & Introduce GameTime (#132)

* Implement Update Timer & Remove Ancient Timers
* WorldTime will be replaced by GameTime which is more accurate.
* World Delay Timer can be view in server info command.

Notice:
* Eluna will have to be updated to support this change or build will fail with it.

* Adding missing string for World Delay time display.

* Fixed CMakeList to include Time Folder which was forgotten.
* Fixed code style in UpdateTime constructor.

* Enable Work Around For Eluna
* Update Initialized UpdateTime Constructor Variables

* Implement GameTime
* Attempt to fix undeclared identifier in Auction House Bot

* Attempt to fix unix compile errors

* Another attempt to fix unix compiling error.

* Remove WorldTimer workaround

No longer necessary as of ba7eea4e40

Co-authored-by: Foereaper <Foereaper@users.noreply.github.com>
This commit is contained in:
Meltie2013 2021-03-04 14:21:54 -06:00 committed by GitHub
parent 53a5c8249d
commit 1c4e25cba0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 691 additions and 426 deletions

View File

@ -1812,14 +1812,14 @@ void AuctionBotSeller::SetPricesOfItem(AHB_Seller_Config& config, uint32& buyp,
double randrange = temp_buyp * 0.4;
uint32 buypMin = (uint32)temp_buyp - (uint32)randrange;
uint32 buypMax = ((uint32)temp_buyp + (uint32)randrange) < temp_buyp ? ACE_Numeric_Limits<uint32>::max() : temp_buyp + randrange;
uint32 buypMax = ((uint32)temp_buyp + (uint32)randrange) < temp_buyp ? std::numeric_limits<uint32>::max() : temp_buyp + randrange;
buyp = (urand(buypMin, buypMax) / 100) + 1;
double urandrange = buyp * 40;
double temp_bidp = buyp * 50;
uint32 bidPmin = (uint32)temp_bidp - (uint32)urandrange;
uint32 bidPmax = ((uint32)temp_bidp + (uint32)urandrange) < temp_bidp ? ACE_Numeric_Limits<uint32>::max() : temp_bidp + urandrange;
uint32 bidPmax = ((uint32)temp_bidp + (uint32)urandrange) < temp_bidp ? std::numeric_limits<uint32>::max() : temp_bidp + urandrange;
bidp = (urand(bidPmin, bidPmax) / 100) + 1;
}

View File

@ -38,6 +38,7 @@
#include "ScriptMgr.h"
#include "World.h"
#include "DisableMgr.h"
#include "GameTime.h"
void WorldSession::HandleBattlemasterHelloOpcode(WorldPacket& recv_data)
{
@ -539,7 +540,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/)
{
continue;
}
uint32 remainingTime = WorldTimer::getMSTimeDiff(WorldTimer::getMSTime(), ginfo.RemoveInviteTime);
uint32 remainingTime = getMSTimeDiff(GameTime::GetGameTimeMS(), ginfo.RemoveInviteTime);
// send status invited to BattleGround
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_JOIN, remainingTime, 0);
SendPacket(&data);
@ -554,7 +555,7 @@ void WorldSession::HandleBattlefieldStatusOpcode(WorldPacket & /*recv_data*/)
uint32 avgTime = bgQueue.GetAverageQueueWaitTime(&ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId));
// send status in BattleGround Queue
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, WorldTimer::getMSTimeDiff(ginfo.JoinTime, WorldTimer::getMSTime()));
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, i, STATUS_WAIT_QUEUE, avgTime, getMSTimeDiff(ginfo.JoinTime, GameTime::GetGameTimeMS()));
SendPacket(&data);
}
}

View File

@ -39,6 +39,7 @@
#include "Language.h"
#include "GameEventMgr.h"
#include "DisableMgr.h"
#include "GameTime.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
@ -163,7 +164,7 @@ GroupQueueInfo* BattleGroundQueue::AddGroup(Player* leader, Group* grp, BattleGr
GroupQueueInfo* ginfo = new GroupQueueInfo;
ginfo->BgTypeId = BgTypeId;
ginfo->IsInvitedToBGInstanceGUID = 0;
ginfo->JoinTime = WorldTimer::getMSTime();
ginfo->JoinTime = GameTime::GetGameTimeMS();
ginfo->RemoveInviteTime = 0;
ginfo->GroupTeam = leader->GetTeam();
@ -183,7 +184,7 @@ GroupQueueInfo* BattleGroundQueue::AddGroup(Player* leader, Group* grp, BattleGr
DEBUG_LOG("Adding Group to BattleGroundQueue bgTypeId : %u, bracket_id : %u, index : %u", BgTypeId, bracketId, index);
uint32 lastOnlineTime = WorldTimer::getMSTime();
uint32 lastOnlineTime = GameTime::GetGameTimeMS();
// add players from group to ginfo
{
@ -259,7 +260,7 @@ GroupQueueInfo* BattleGroundQueue::AddGroup(Player* leader, Group* grp, BattleGr
void BattleGroundQueue::PlayerInvitedToBGUpdateAverageWaitTime(GroupQueueInfo* ginfo, BattleGroundBracketId bracket_id)
{
uint32 timeInQueue = WorldTimer::getMSTimeDiff(ginfo->JoinTime, WorldTimer::getMSTime());
uint32 timeInQueue = getMSTimeDiff(ginfo->JoinTime, GameTime::GetGameTimeMS());
uint8 team_index = TEAM_INDEX_ALLIANCE; // default set to BG_TEAM_ALLIANCE - or non rated arenas!
if (ginfo->GroupTeam == HORDE)
@ -422,7 +423,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo* ginfo, BattleGround* bg,
BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId);
BattleGroundBracketId bracket_id = bg->GetBracketId();
ginfo->RemoveInviteTime = WorldTimer::getMSTime() + INVITE_ACCEPT_WAIT_TIME;
ginfo->RemoveInviteTime = GameTime::GetGameTimeMS() + INVITE_ACCEPT_WAIT_TIME;
// loop through the players
for (GroupQueueInfoPlayers::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr)
@ -610,7 +611,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BattleGroundBracketId bracket_id, uint
// this could be 2 cycles but i'm checking only first team in queue - it can cause problem -
// if first is invited to BG and seconds timer expired, but we can ignore it, because players have only 80 seconds to click to enter bg
// and when they click or after 80 seconds the queue info is removed from queue
uint32 time_before = WorldTimer::getMSTime() - sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
uint32 time_before = GameTime::GetGameTimeMS() - sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH);
for (uint8 i = 0; i < PVP_TEAM_COUNT; ++i)
{
if (!m_QueuedGroups[bracket_id][BG_QUEUE_PREMADE_ALLIANCE + i].empty())

View File

@ -57,6 +57,10 @@ source_group("References" FILES ${SRC_GRP_REFERENCES})
file(GLOB SRC_GRP_SERVER Server/*.cpp Server/*.h)
source_group("Server" FILES ${SRC_GRP_SERVER})
#Time group
file(GLOB SRC_GRP_TIME Time/*.cpp Time/*.h)
source_group("Time" FILES ${SRC_GRP_TIME})
#Tools group
file(GLOB SRC_GRP_TOOL Tools/*.cpp Tools/*.h)
source_group("Tool" FILES ${SRC_GRP_TOOL})
@ -219,6 +223,7 @@ add_library(game STATIC
${SRC_GRP_OUTDOOR_PVP}
${SRC_GRP_REFERENCES}
${SRC_GRP_SERVER}
${SRC_GRP_TIME}
${SRC_GRP_TOOL}
${SRC_GRP_VMAPS}
${SRC_GRP_WARDEN}
@ -244,6 +249,7 @@ target_include_directories(game
OutdoorPvP
References
Server
Time
Tools
vmap
Warden

View File

@ -31,6 +31,7 @@
#include "GridNotifiersImpl.h" // for mmap manager
#include "CellImpl.h"
#include "movement/MoveSplineInit.h"
#include "GameTime.h"
#include <fstream>
#include <map>
#include <typeinfo>
@ -320,7 +321,7 @@ bool ChatHandler::HandleMmapTestArea(char* args)
PSendSysMessage("Found " SIZEFMTD " Creatures.", creatureList.size());
uint32 paths = 0;
uint32 uStartTime = WorldTimer::getMSTime();
uint32 uStartTime = GameTime::GetGameTimeMS();
float gx, gy, gz;
m_session->GetPlayer()->GetPosition(gx, gy, gz);
@ -331,7 +332,7 @@ bool ChatHandler::HandleMmapTestArea(char* args)
++paths;
}
uint32 uPathLoadTime = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime());
uint32 uPathLoadTime = getMSTimeDiff(uStartTime, GameTime::GetGameTimeMS());
PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime);
}
else
@ -389,7 +390,7 @@ bool ChatHandler::HandleMmapTestHeight(char* args)
summoned->CastSpell(summoned, 8599, false);
uint32 tries = 1;
uint32 successes = 0;
uint32 startTime = WorldTimer::getMSTime();
uint32 startTime = GameTime::GetGameTimeMS();
for (; tries < 500; ++tries)
{
unit->GetPosition(gx, gy, gz);
@ -403,7 +404,7 @@ bool ChatHandler::HandleMmapTestHeight(char* args)
}
}
}
uint32 genTime = WorldTimer::getMSTimeDiff(startTime, WorldTimer::getMSTime());
uint32 genTime = getMSTimeDiff(startTime, GameTime::GetGameTimeMS());
PSendSysMessage("Generated %u valid points for %u try in %ums.", successes, tries, genTime);
return true;
}

View File

@ -27,6 +27,7 @@
#include "World.h"
#include "Config.h"
#include "SystemConfig.h"
#include "UpdateTime.h"
#include "revision.h"
/**********************************************************************
@ -41,6 +42,7 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/)
uint32 maxActiveClientsNum = sWorld.GetMaxActiveSessionCount();
uint32 maxQueuedClientsNum = sWorld.GetMaxQueuedSessionCount();
std::string str = secsToTimeString(sWorld.GetUptime());
uint32 updateTime = sWorldUpdateTime.GetLastUpdateTime();
char const* full;
full = REVISION_NR;
@ -66,6 +68,7 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/)
PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion());
PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
PSendSysMessage(LANG_UPTIME, str.c_str());
PSendSysMessage("World Delay: %u", updateTime); // ToDo: move to language string
return true;
}

View File

@ -45,7 +45,7 @@ RandomMovementGenerator<Creature>::RandomMovementGenerator(const Creature& creat
{
float respX, respY, respZ, respO, wander_distance;
creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance);
i_nextMoveTime = ShortTimeTracker(0);
i_nextMoveTime = TimeTracker(0);
i_x = respX;
i_y = respY;
i_z = respZ;

View File

@ -46,7 +46,7 @@ class RandomMovementGenerator
bool Update(T&, const uint32&);
MovementGeneratorType GetMovementGeneratorType() const override { return RANDOM_MOTION_TYPE; }
private:
ShortTimeTracker i_nextMoveTime;
TimeTracker i_nextMoveTime;
float i_x, i_y, i_z;
float i_radius;
float i_verticalZ;

View File

@ -69,7 +69,7 @@ class TargetedMovementGeneratorMedium
bool RequiresNewPosition(T& owner, float x, float y, float z) const;
virtual float GetDynamicTargetDistance(T& /*owner*/, bool /*forRangeCheck*/) const { return i_offset; }
ShortTimeTracker i_recheckDistance;
TimeTracker i_recheckDistance;
float i_offset;
float i_angle;
G3D::Vector3 m_prevTargetPos;

View File

@ -390,11 +390,11 @@ void WaypointMovementGenerator<Creature>::GetPathInformation(std::ostringstream&
void WaypointMovementGenerator<Creature>::AddToWaypointPauseTime(int32 waitTimeDiff)
{
if (!i_nextMoveTime.Passed())
i_nextMoveTime.Update(waitTimeDiff);
if (i_nextMoveTime.Passed())
{
// Prevent <= 0, the code in Update requires to catch the change from moving to not moving
int32 newWaitTime = i_nextMoveTime.GetExpiry() + waitTimeDiff;
i_nextMoveTime.Reset(newWaitTime > 0 ? newWaitTime : 1);
i_nextMoveTime.Reset(0);
return;
}
}

View File

@ -99,7 +99,7 @@ class WaypointMovementGenerator<Creature>
void OnArrived(Creature&);
void StartMove(Creature&);
ShortTimeTracker i_nextMoveTime;
TimeTracker i_nextMoveTime;
bool m_isArrivalDone;
uint32 m_lastReachedWaypoint;

View File

@ -44,6 +44,7 @@
#include "movement/packet_builder.h"
#include "CreatureLinkingMgr.h"
#include "Chat.h"
#include "GameTime.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#include "ElunaEventMgr.h"
@ -322,7 +323,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint8 updateFlags) const
// 0x2
if (updateFlags & UPDATEFLAG_TRANSPORT)
{
*data << uint32(WorldTimer::getMSTime()); // ms time
*data << uint32(GameTime::GetGameTimeMS()); // ms time
}
}

View File

@ -31,6 +31,7 @@
#include "UpdateData.h"
#include "ObjectGuid.h"
#include "Camera.h"
#include "GameTime.h"
#include <set>
@ -114,13 +115,13 @@ class WorldUpdateCounter
{
if (!m_tmStart)
{
m_tmStart = WorldTimer::tickPrevTime();
m_tmStart = GameTime::GetGameTimeMS();
}
return WorldTimer::getMSTimeDiff(m_tmStart, WorldTimer::tickTime());
return getMSTimeDiff(m_tmStart, GameTime::GetGameTimeMS());
}
void Reset() { m_tmStart = WorldTimer::tickTime(); }
void Reset() { m_tmStart = GameTime::GetGameTimeMS(); }
private:
uint32 m_tmStart;

View File

@ -52,6 +52,7 @@
#include "movement/MoveSplineInit.h"
#include "movement/MoveSpline.h"
#include "CreatureLinkingMgr.h"
#include "GameTime.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#include "ElunaEventMgr.h"
@ -59,17 +60,6 @@
#include <math.h>
#ifdef WIN32
inline uint32 getMSTime() { return GetTickCount(); }
#else
inline uint32 getMSTime()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
#endif
float baseMoveSpeed[MAX_MOVE_TYPE] =
{
2.5f, // MOVE_WALK
@ -170,12 +160,12 @@ void MovementInfo::Write(ByteBuffer& data) const
bool GlobalCooldownMgr::HasGlobalCooldown(SpellEntry const* spellInfo) const
{
GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != m_GlobalCooldowns.end() && itr->second.duration && WorldTimer::getMSTimeDiff(itr->second.cast_time, WorldTimer::getMSTime()) < itr->second.duration;
return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, GameTime::GetGameTimeMS()) < itr->second.duration;
}
void GlobalCooldownMgr::AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, WorldTimer::getMSTime());
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, GameTime::GetGameTimeMS());
}
void GlobalCooldownMgr::CancelGlobalCooldown(SpellEntry const* spellInfo)
@ -485,7 +475,7 @@ bool Unit::haveOffhandWeapon() const
void Unit::SendHeartBeat()
{
m_movementInfo.UpdateTime(WorldTimer::getMSTime());
m_movementInfo.UpdateTime(GameTime::GetGameTimeMS());
WorldPacket data(MSG_MOVE_HEARTBEAT, 31);
data << GetPackGUID();
data << m_movementInfo;
@ -8825,7 +8815,7 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)
}
// If last spell was casted more than 15 seconds ago - reset the count.
if (i->stack == 0 && WorldTimer::getMSTimeDiff(i->hitTime, WorldTimer::getMSTime()) > 15 * IN_MILLISECONDS)
if (i->stack == 0 && getMSTimeDiff(i->hitTime, GameTime::GetGameTimeMS()) > 15 * IN_MILLISECONDS)
{
i->hitCount = DIMINISHING_LEVEL_1;
return DIMINISHING_LEVEL_1;
@ -8854,7 +8844,7 @@ void Unit::IncrDiminishing(DiminishingGroup group)
}
return;
}
m_Diminishing.push_back(DiminishingReturn(group, WorldTimer::getMSTime(), DIMINISHING_LEVEL_2));
m_Diminishing.push_back(DiminishingReturn(group, GameTime::GetGameTimeMS(), DIMINISHING_LEVEL_2));
}
void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32& duration, Unit* caster, DiminishingLevels Level, bool isReflected)
@ -8903,7 +8893,7 @@ void Unit::ApplyDiminishingAura(DiminishingGroup group, bool apply)
// Remember time after last aura from group removed
if (i->stack == 0)
{
i->hitTime = WorldTimer::getMSTime();
i->hitTime = GameTime::GetGameTimeMS();
}
}
break;

View File

@ -3850,7 +3850,7 @@ protected:
UnitVisibility m_Visibility;
Position m_last_notified_position;
bool m_AINotifyScheduled;
ShortTimeTracker m_movesplineTimer;
TimeTracker m_movesplineTimer;
Diminishing m_Diminishing;
// Manage all Units threatening us

View File

@ -163,7 +163,7 @@ class OutdoorPvPMgr
*/
CapturePointSliderMap m_capturePointSlider;
ShortIntervalTimer m_updateTimer; /**< update interval */
IntervalTimer m_updateTimer; /**< update interval */
};
#define sOutdoorPvPMgr MaNGOS::Singleton<OutdoorPvPMgr>::Instance()

View File

@ -0,0 +1,75 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2021 MaNGOS <https://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "GameTime.h"
#include "Timer.h"
namespace GameTime
{
time_t const StartTime = time(nullptr);
time_t GameTime = 0;
uint32 GameMSTime = 0;
std::chrono::system_clock::time_point GameTimeSystemPoint = std::chrono::system_clock::time_point::min();
std::chrono::steady_clock::time_point GameTimeSteadyPoint = std::chrono::steady_clock::time_point::min();
time_t GetStartTime()
{
return StartTime;
}
time_t GetGameTime()
{
return GameTime;
}
uint32 GetGameTimeMS()
{
return GameMSTime;
}
std::chrono::system_clock::time_point GetGameTimeSystemPoint()
{
return GameTimeSystemPoint;
}
std::chrono::steady_clock::time_point GetGameTimeSteadyPoint()
{
return GameTimeSteadyPoint;
}
uint32 GetUptime()
{
return uint32(GameTime - StartTime);
}
void UpdateGameTimers()
{
GameTime = time(nullptr);
GameMSTime = getMSTime();
GameTimeSystemPoint = std::chrono::system_clock::now();
GameTimeSteadyPoint = std::chrono::steady_clock::now();
}
}

55
src/game/Time/GameTime.h Normal file
View File

@ -0,0 +1,55 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2021 MaNGOS <https://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef GAMETIME_H
#define GAMETIME_H
#include "Define.h"
#include <chrono>
namespace GameTime
{
// Server Start Time
time_t GetStartTime();
// Current Server Time (unix) in seconds
time_t GetGameTime();
// Milliseconds since Server Start
uint32 GetGameTimeMS();
// Current chrono system_clock time point
std::chrono::system_clock::time_point GetGameTimeSystemPoint();
// Current chrono steady_clock time point
std::chrono::steady_clock::time_point GetGameTimeSteadyPoint();
// Uptime (in seconds)
uint32 GetUptime();
void UpdateGameTimers();
}
#endif

View File

@ -0,0 +1,146 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2021 MaNGOS <https://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "UpdateTime.h"
#include "Timer.h"
#include "Config.h"
#include "Log.h"
WorldUpdateTime sWorldUpdateTime;
UpdateTime::UpdateTime() : _averageUpdateTime(0), _totalUpdateTime(0), _updateTimeTableIndex(0), _maxUpdateTime(0),
_maxUpdateTimeOfLastTable(0), _maxUpdateTimeOfCurrentTable(0), _updateTimeDataTable() { }
uint32 UpdateTime::GetAverageUpdateTime() const
{
return _averageUpdateTime;
}
uint32 UpdateTime::GetTimeWeightedAverageUpdateTime() const
{
uint32 sum = 0, weightsum = 0;
for (uint32 diff : _updateTimeDataTable)
{
sum += diff * diff;
weightsum += diff;
}
return sum / weightsum;
}
uint32 UpdateTime::GetMaxUpdateTime() const
{
return _maxUpdateTime;
}
uint32 UpdateTime::GetMaxUpdatTimeOfCurrentTable() const
{
return std::max(_maxUpdateTimeOfCurrentTable, _maxUpdateTimeOfLastTable);
}
uint32 UpdateTime::GetLastUpdateTime() const
{
return _updateTimeDataTable[_updateTimeTableIndex != 0 ? _updateTimeTableIndex - 1 : _updateTimeDataTable.size() - 1];
}
void UpdateTime::UpdateWithDiff(uint32 diff)
{
_totalUpdateTime = _totalUpdateTime - _updateTimeDataTable[_updateTimeTableIndex] + diff;
_updateTimeDataTable[_updateTimeTableIndex] = diff;
if (diff > _maxUpdateTime)
{
_maxUpdateTime = diff;
}
if (diff > _maxUpdateTimeOfCurrentTable)
{
_maxUpdateTimeOfCurrentTable = diff;
}
if (++_updateTimeTableIndex >= _updateTimeDataTable.size())
{
_updateTimeTableIndex = 0;
_maxUpdateTimeOfLastTable = _maxUpdateTimeOfCurrentTable;
_maxUpdateTimeOfCurrentTable = 0;
}
if (_updateTimeDataTable[_updateTimeDataTable.size() - 1])
{
_averageUpdateTime = _totalUpdateTime / _updateTimeDataTable.size();
}
else if (_updateTimeTableIndex)
{
_averageUpdateTime = _totalUpdateTime / _updateTimeTableIndex;
}
}
void UpdateTime::RecordUpdateTimeReset()
{
_recordedTime = getMSTime();
}
void UpdateTime::_RecordUpdateTimeDuration(std::string const& text, uint32 minUpdateTime)
{
uint32 thisTime = getMSTime();
uint32 diff = getMSTimeDiff(_recordedTime, thisTime);
if (diff > minUpdateTime)
{
sLog.outError("Record Update Time of %s: %u", text.c_str(), diff);
}
_recordedTime = thisTime;
}
void WorldUpdateTime::LoadFromConfig()
{
// ToDo: move to configuration
_recordUpdateTimeInverval = 60000;
_recordUpdateTimeMin = 100;
}
void WorldUpdateTime::SetRecordUpdateTimeInterval(uint32 t)
{
_recordUpdateTimeInverval = t;
}
void WorldUpdateTime::RecordUpdateTime(uint32 gameTimeMs, uint32 diff, uint32 sessionCount)
{
if (_recordUpdateTimeInverval > 0 && diff > _recordUpdateTimeMin)
{
if (getMSTimeDiff(_lastRecordTime, gameTimeMs) > _recordUpdateTimeInverval)
{
sLog.outString("Update time diff: %u. Players online: %u", GetAverageUpdateTime(), sessionCount);
_lastRecordTime = gameTimeMs;
}
}
}
void WorldUpdateTime::RecordUpdateTimeDuration(std::string const& text)
{
_RecordUpdateTimeDuration(text, _recordUpdateTimeMin);
}

View File

@ -0,0 +1,85 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2021 MaNGOS <https://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef UPDATETIME_H
#define UPDATETIME_H
#include "Common.h"
#include "Timer.h"
#include <array>
#include <string>
#define AVG_DIFF_COUNT 500
class UpdateTime
{
using DiffTableArray = std::array<uint32, AVG_DIFF_COUNT>;
public:
uint32 GetAverageUpdateTime() const;
uint32 GetTimeWeightedAverageUpdateTime() const;
uint32 GetMaxUpdateTime() const;
uint32 GetMaxUpdatTimeOfCurrentTable() const;
uint32 GetLastUpdateTime() const;
void UpdateWithDiff(uint32 diff);
void RecordUpdateTimeReset();
protected:
UpdateTime();
void _RecordUpdateTimeDuration(std::string const& text, uint32 minUpdateTime);
private:
DiffTableArray _updateTimeDataTable;
uint32 _averageUpdateTime;
uint32 _totalUpdateTime;
uint32 _updateTimeTableIndex;
uint32 _maxUpdateTime;
uint32 _maxUpdateTimeOfLastTable;
uint32 _maxUpdateTimeOfCurrentTable;
uint32 _recordedTime;
};
class WorldUpdateTime : public UpdateTime
{
public:
WorldUpdateTime() : UpdateTime(), _recordUpdateTimeInverval(0), _recordUpdateTimeMin(0), _lastRecordTime(0) { }
void LoadFromConfig();
void SetRecordUpdateTimeInterval(uint32 t);
void RecordUpdateTime(uint32 gameTimeMs, uint32 diff, uint32 sessionCount);
void RecordUpdateTimeDuration(std::string const& text);
private:
uint32 _recordUpdateTimeInverval;
uint32 _recordUpdateTimeMin;
uint32 _lastRecordTime;
};
extern WorldUpdateTime sWorldUpdateTime;
#endif

View File

@ -35,6 +35,7 @@
#include "Util.h"
#include "Warden.h"
#include "AccountMgr.h"
#include "GameTime.h"
Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
_module(NULL), _state(WardenState::STATE_INITIAL)
@ -42,7 +43,7 @@ Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTi
memset(_inputKey, 0, sizeof(_inputKey));
memset(_outputKey, 0, sizeof(_outputKey));
memset(_seed, 0, sizeof(_seed));
_previousTimestamp = WorldTimer::getMSTime();
_previousTimestamp = GameTime::GetGameTimeMS();
}
Warden::~Warden()
@ -128,7 +129,7 @@ void Warden::RequestModule()
void Warden::Update()
{
uint32 currentTimestamp = WorldTimer::getMSTime();
uint32 currentTimestamp = GameTime::GetGameTimeMS();
uint32 diff = currentTimestamp - _previousTimestamp;
_previousTimestamp = currentTimestamp;

View File

@ -36,6 +36,7 @@
#include "Util.h"
#include "WardenMac.h"
#include "WardenModuleMac.h"
#include "GameTime.h"
WardenMac::WardenMac() : Warden() { }
@ -177,7 +178,7 @@ void WardenMac::HandleHashResult(ByteBuffer &buff)
_inputCrypto.Init(_inputKey);
_outputCrypto.Init(_outputKey);
_previousTimestamp = WorldTimer::getMSTime();
_previousTimestamp = GameTime::GetGameTimeMS();
}
void WardenMac::RequestData()

View File

@ -39,6 +39,7 @@
#include "WardenWin.h"
#include "WardenModuleWin.h"
#include "WardenCheckMgr.h"
#include "GameTime.h"
WardenWin::WardenWin() : Warden(), _serverTicks(0) {}
@ -156,7 +157,7 @@ void WardenWin::HandleHashResult(ByteBuffer &buff)
_inputCrypto.Init(_inputKey);
_outputCrypto.Init(_outputKey);
_previousTimestamp = WorldTimer::getMSTime();
_previousTimestamp = GameTime::GetGameTimeMS();
}
void WardenWin::RequestData()
@ -179,7 +180,7 @@ void WardenWin::RequestData()
sWardenCheckMgr->GetWardenCheckIds(false, build, _otherChecksTodo);
}
_serverTicks = WorldTimer::getMSTime();
_serverTicks = GameTime::GetGameTimeMS();
_currentChecks.clear();
@ -355,7 +356,7 @@ void WardenWin::HandleData(ByteBuffer &buff)
uint32 newClientTicks;
buff >> newClientTicks;
uint32 ticksNow = WorldTimer::getMSTime();
uint32 ticksNow = GameTime::GetGameTimeMS();
uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks);
sLog.outWarden("ServerTicks %u, RequestTicks %u, ClientTicks %u", ticksNow, _serverTicks, newClientTicks); // Now, At request, At response

View File

@ -45,6 +45,7 @@
#include "Language.h"
#include "Chat.h"
#include "SpellMgr.h"
#include "GameTime.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
@ -799,7 +800,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
#endif
/* Sync player's in-game time with server time */
pCurrChar->SetInGameTime(WorldTimer::getMSTime());
pCurrChar->SetInGameTime(GameTime::GetGameTimeMS());
/* Send logon notification to player's group
* This is sent after player is added to the world so that player receives it too */

View File

@ -275,7 +275,7 @@ class TerrainInfo : public Referencable<AtomicLong>
int16 m_GridRef[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
// global garbage collection timer
ShortIntervalTimer i_timer;
IntervalTimer i_timer;
typedef ACE_Thread_Mutex LOCK_TYPE;
LOCK_TYPE m_mutex;

View File

@ -575,7 +575,7 @@ bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo) const
void WorldSession::HandleMoverRelocation(MovementInfo& movementInfo)
{
//uint32 mstime = WorldTimer::getMSTime();
//uint32 mstime = GameTime::GetGameTimeMS();
//if (m_clientTimeDelay == 0)
// m_clientTimeDelay = mstime - movementInfo.GetTime();

View File

@ -30,6 +30,7 @@
#include "ObjectMgr.h"
#include "ObjectGuid.h"
#include "Path.h"
#include "GameTime.h"
#include "WorldPacket.h"
#include "DBCStores.h"
@ -655,7 +656,7 @@ void GlobalTransport::Update(uint32 /*update_diff*/, uint32 /*p_time*/)
return;
}
m_timer = WorldTimer::getMSTime() % m_period;
m_timer = GameTime::GetGameTimeMS() % m_period;
while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime))
{
MoveToNextWayPoint();

View File

@ -100,7 +100,7 @@ class Weather
uint32 m_zone;
WeatherType m_type;
float m_grade;
ShortIntervalTimer m_timer;
IntervalTimer m_timer;
WeatherZoneChances const* m_weatherChances;
bool m_isPermanentWeather;
};

View File

@ -74,6 +74,8 @@
#include "Language.h"
#include "CommandMgr.h"
#include "revision.h"
#include "UpdateTime.h"
#include "GameTime.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
@ -962,7 +964,7 @@ void World::SetInitialWorldSettings()
srand((unsigned int)time(NULL));
///- Time server startup
uint32 uStartTime = WorldTimer::getMSTime();
uint32 startupBegin = GameTime::GetGameTimeMS();
///- Initialize detour memory management
dtAllocSetCustom(dtCustomAlloc, dtCustomFree);
@ -1500,8 +1502,8 @@ void World::SetInitialWorldSettings()
showFooter();
uint32 uStartInterval = WorldTimer::getMSTimeDiff(uStartTime, WorldTimer::getMSTime());
sLog.outString("SERVER STARTUP TIME: %i minutes %i seconds", uStartInterval / 60000, (uStartInterval % 60000) / 1000);
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
sLog.outString("SERVER STARTUP TIME: %i minutes %i seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
sLog.outString();
}
@ -1676,6 +1678,8 @@ void World::Update(uint32 diff)
///- Update the game time and check for shutdown time
_UpdateGameTime();
sWorldUpdateTime.UpdateWithDiff(diff);
///-Update mass mailer tasks if any
sMassMailMgr.Update();

View File

@ -98,7 +98,7 @@ struct DynTreeImpl : public ParentTree/*, public Intersectable*/
}
}
ShortTimeTracker rebalance_timer;
TimeTracker rebalance_timer;
int unbalanced_times;
};

View File

@ -27,7 +27,6 @@
#include "World.h"
#include "Log.h"
AntiFreezeThread::AntiFreezeThread(uint32 delay) : delaytime_(delay)
{
m_loops = 0;
@ -49,12 +48,12 @@ int AntiFreezeThread::svc(void)
return 0;
}
sLog.outString("AntiFreeze Thread started (%u seconds max stuck time)", delaytime_/1000);
sLog.outString("AntiFreeze Thread started (%u seconds max stuck time)", delaytime_ / 1000);
while (!World::IsStopped())
{
ACE_OS::sleep(1);
uint32 curtime = WorldTimer::getMSTime();
uint32 curtime = getMSTime();
// normal work
if (w_loops != World::m_worldLoopCounter.value())
@ -63,12 +62,13 @@ int AntiFreezeThread::svc(void)
w_loops = World::m_worldLoopCounter.value();
}
// possible freeze
else if (WorldTimer::getMSTimeDiff(w_lastchange, curtime) > delaytime_)
else if (getMSTimeDiff(w_lastchange, curtime) > delaytime_)
{
sLog.outError("World Thread hangs, kicking out server!");
*((uint32 volatile*)NULL) = 0; // bang crash
}
}
sLog.outString("AntiFreeze Thread stopped.");
return 0;
}

View File

@ -36,6 +36,9 @@
#include "MapManager.h"
#include "Database/DatabaseEnv.h"
#include <chrono>
#include <thread>
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
@ -71,38 +74,35 @@ int WorldThread::open(void* unused)
/// Heartbeat for the World
int WorldThread::svc()
{
uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST
uint32 realCurrTime = 0;
uint32 realPrevTime = getMSTime();
sLog.outString("World Updater Thread started (%dms min update interval)", WORLD_SLEEP_CONST);
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
++World::m_worldLoopCounter;
realCurrTime = getMSTime();
uint32 diff = WorldTimer::tick();
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
sWorld.Update(diff);
realPrevTime = realCurrTime;
// diff (D0) include time of previous sleep (d0) + tick time (t0)
// we want that next d1 + t1 == WORLD_SLEEP_CONST
// we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement
// d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0
if (diff <= WORLD_SLEEP_CONST + prevSleepTime)
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
// we know exactly how long it took to update the world, if the update took less than WORLD_SLEEP_CONST, sleep for WORLD_SLEEP_CONST - world update time
if (executionTimeDiff < WORLD_SLEEP_CONST)
{
prevSleepTime = WORLD_SLEEP_CONST + prevSleepTime - diff;
ACE_Based::Thread::Sleep(prevSleepTime);
}
else
{
prevSleepTime = 0;
std::this_thread::sleep_for(std::chrono::milliseconds(WORLD_SLEEP_CONST - executionTimeDiff));
}
#ifdef _WIN32
if (m_ServiceStatus == 0) //service stopped
if (m_ServiceStatus == 0) // service stopped
{
World::StopNow(SHUTDOWN_EXIT_CODE);
}
while (m_ServiceStatus == 2) //service paused
while (m_ServiceStatus == 2) // service paused
Sleep(1000);
#endif
}

View File

@ -207,7 +207,7 @@ bool MySQLConnection::_Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD**
return 0;
}
uint32 _s = WorldTimer::getMSTime();
uint32 _s = getMSTime();
if (mysql_query(mMysql, sql))
{
@ -217,7 +217,7 @@ bool MySQLConnection::_Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD**
}
else
{
DEBUG_FILTER_LOG(LOG_FILTER_SQL_TEXT, "[%u ms] SQL: %s", WorldTimer::getMSTimeDiff(_s, WorldTimer::getMSTime()), sql);
DEBUG_FILTER_LOG(LOG_FILTER_SQL_TEXT, "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
}
*pResult = mysql_store_result(mMysql);
@ -289,7 +289,7 @@ bool MySQLConnection::Execute(const char* sql)
}
{
uint32 _s = WorldTimer::getMSTime();
uint32 _s = getMSTime();
if (mysql_query(mMysql, sql))
{
@ -299,7 +299,7 @@ bool MySQLConnection::Execute(const char* sql)
}
else
{
DEBUG_FILTER_LOG(LOG_FILTER_SQL_TEXT, "[%u ms] SQL: %s", WorldTimer::getMSTimeDiff(_s, WorldTimer::getMSTime()), sql);
DEBUG_FILTER_LOG(LOG_FILTER_SQL_TEXT, "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
}
// end guarded block
}

View File

@ -357,34 +357,37 @@ FILE* Log::openGmlogPerAccount(uint32 account)
void Log::outTimestamp(FILE* file)
{
time_t t = time(NULL);
tm* aTm = localtime(&t);
time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm aTm = localtime_r(tt);
// YYYY year
// MM month (2 digits 01-12)
// DD day (2 digits 01-31)
// HH hour (2 digits 00-23)
// MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59)
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
}
void Log::outTime()
{
time_t t = time(NULL);
tm* aTm = localtime(&t);
time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm aTm = localtime_r(tt);
// YYYY year
// MM month (2 digits 01-12)
// DD day (2 digits 01-31)
// HH hour (2 digits 00-23)
// MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59)
printf("%02d:%02d:%02d ", aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
printf("%02d:%02d:%02d ", aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
}
std::string Log::GetTimestampStr()
{
time_t t = time(NULL);
tm* aTm = localtime(&t);
time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::tm aTm = localtime_r(tt);
// YYYY year
// MM month (2 digits 01-12)
// DD day (2 digits 01-31)
@ -392,7 +395,7 @@ std::string Log::GetTimestampStr()
// MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59)
char buf[20];
snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
return std::string(buf);
}

View File

@ -0,0 +1,51 @@
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
* Copyright (C) 2005-2021 MaNGOS <https://getmangos.eu>
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#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;
/// time_point shorthand typedefs
typedef std::chrono::steady_clock::time_point TimePoint;
typedef std::chrono::system_clock::time_point SystemTimePoint;
constexpr std::chrono::hours operator""_days(unsigned long long days)
{
return std::chrono::hours(days * Hours(24));
}
#endif

View File

@ -25,315 +25,177 @@
#ifndef MANGOS_TIMER_H
#define MANGOS_TIMER_H
#include "Common/Common.h"
#include <ace/OS_NS_sys_time.h>
#include "Common.h"
#include "Duration.h"
/**
* @brief
*
*/
class WorldTimer
// New Method
inline std::chrono::steady_clock::time_point GetApplicationStartTime()
{
public:
using namespace std::chrono;
/**
* @brief get current server time
*
* @return uint32
*/
static uint32 getMSTime();
static const steady_clock::time_point ApplicationStartTime = steady_clock::now();
/**
* @brief get time difference between two timestamps
*
* @param oldMSTime
* @param newMSTime
* @return uint32
*/
static inline uint32 getMSTimeDiff(const uint32& oldMSTime, const uint32& newMSTime)
{
if (oldMSTime > newMSTime)
{
const uint32 diff_1 = (uint32(0xFFFFFFFF) - oldMSTime) + newMSTime;
const uint32 diff_2 = oldMSTime - newMSTime;
return ApplicationStartTime;
}
return std::min(diff_1, diff_2);
}
inline uint32 getMSTime()
{
using namespace std::chrono;
return newMSTime - oldMSTime;
}
return uint32(duration_cast<milliseconds>(steady_clock::now() - GetApplicationStartTime()).count());
}
/**
* @brief get last world tick time
*
* @return uint32
*/
static uint32 tickTime();
/**
* @brief get previous world tick time
*
* @return uint32
*/
static uint32 tickPrevTime();
/**
* @brief tick world timer
*
* @return uint32
*/
static uint32 tick();
inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
{
// getMSTime() have limited data range and this is case when it overflow in this tick
if (oldMSTime > newMSTime)
{
return (0xFFFFFFFF - oldMSTime) + newMSTime;
}
else
{
return newMSTime - oldMSTime;
}
}
private:
/**
* @brief
*
*/
WorldTimer();
/**
* @brief
*
* @param
*/
WorldTimer(const WorldTimer&);
inline uint32 getMSTimeDiff(uint32 oldMSTime, std::chrono::steady_clock::time_point newTime)
{
using namespace std::chrono;
/**
* @brief analogue to getMSTime() but it persists m_SystemTickTime
*
* @param savetime
* @return uint32
*/
static uint32 getMSTime_internal();
uint32 newMSTime = uint32(duration_cast<milliseconds>(newTime - GetApplicationStartTime()).count());
return getMSTimeDiff(oldMSTime, newMSTime);
}
static uint32 m_iTime; /**< TODO */
static uint32 m_iPrevTime; /**< TODO */
inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
{
return getMSTimeDiff(oldMSTime, getMSTime());
}
struct IntervalTimer
{
public:
IntervalTimer() : _interval(0), _current(0) { }
void Update(time_t diff)
{
_current += diff;
if (_current < 0)
{
_current = 0;
}
}
bool Passed()
{
return _current >= _interval;
}
void Reset()
{
if (_current >= _interval)
{
_current %= _interval;
}
}
void SetCurrent(time_t current)
{
_current = current;
}
void SetInterval(time_t interval)
{
_interval = interval;
}
time_t GetInterval() const
{
return _interval;
}
time_t GetCurrent() const
{
return _current;
}
private:
time_t _interval;
time_t _current;
};
/**
* @brief
*
*/
class IntervalTimer
{
public:
/**
* @brief
*
*/
IntervalTimer() : _interval(0), _current(0) {}
/**
* @brief
*
* @param diff
*/
void Update(time_t diff)
{
_current += diff;
if (_current < 0)
{
_current = 0;
}
}
/**
* @brief
*
* @return bool
*/
bool Passed() const { return _current >= _interval; }
/**
* @brief
*
*/
void Reset()
{
if (_current >= _interval)
{
_current -= _interval;
}
}
/**
* @brief
*
* @param current
*/
void SetCurrent(time_t current) { _current = current; }
/**
* @brief
*
* @param interval
*/
void SetInterval(time_t interval) { _interval = interval; }
/**
* @brief
*
* @return time_t
*/
time_t GetInterval() const { return _interval; }
/**
* @brief
*
* @return time_t
*/
time_t GetCurrent() const { return _current; }
private:
time_t _interval; /**< TODO */
time_t _current; /**< TODO */
};
/**
* @brief
*
*/
class ShortIntervalTimer
{
public:
/**
* @brief
*
*/
ShortIntervalTimer() : _interval(0), _current(0) {}
/**
* @brief
*
* @param diff
*/
void Update(uint32 diff)
{
_current += diff;
}
/**
* @brief
*
* @return bool
*/
bool Passed() const { return _current >= _interval; }
/**
* @brief
*
*/
void Reset()
{
if (_current >= _interval)
{
_current -= _interval;
}
}
/**
* @brief
*
* @param current
*/
void SetCurrent(uint32 current) { _current = current; }
/**
* @brief
*
* @param interval
*/
void SetInterval(uint32 interval) { _interval = interval; }
/**
* @brief
*
* @return uint32
*/
uint32 GetInterval() const { return _interval; }
/**
* @brief
*
* @return uint32
*/
uint32 GetCurrent() const { return _current; }
private:
uint32 _interval; /**< TODO */
uint32 _current; /**< TODO */
};
/**
* @brief
*
*/
struct TimeTracker
{
public:
/**
* @brief
*
* @param expiry
*/
TimeTracker(time_t expiry) : i_expiryTime(expiry) {}
/**
* @brief
*
* @param diff
*/
void Update(time_t diff) { i_expiryTime -= diff; }
/**
* @brief
*
* @return bool
*/
bool Passed() const { return (i_expiryTime <= 0); }
/**
* @brief
*
* @param interval
*/
void Reset(time_t interval) { i_expiryTime = interval; }
/**
* @brief
*
* @return time_t
*/
time_t GetExpiry() const { return i_expiryTime; }
public:
TimeTracker(int32 expiry = 0) : _expiryTime(expiry) { }
TimeTracker(Milliseconds expiry) : _expiryTime(expiry) { }
private:
time_t i_expiryTime; /**< TODO */
void Update(int32 diff)
{
Update(Milliseconds(diff));
}
void Update(Milliseconds diff)
{
_expiryTime -= diff;
}
bool Passed() const
{
return _expiryTime <= Seconds(0);
}
void Reset(int32 expiry)
{
Reset(Milliseconds(expiry));
}
void Reset(Milliseconds expiry)
{
_expiryTime = expiry;
}
Milliseconds GetExpiry() const
{
return _expiryTime;
}
private:
Milliseconds _expiryTime;
};
/**
* @brief
*
*/
struct ShortTimeTracker
struct PeriodicTimer
{
public:
/**
* @brief
*
* @param expiry
*/
ShortTimeTracker(int32 expiry = 0) : i_expiryTime(expiry) {}
/**
* @brief
*
* @param diff
*/
void Update(int32 diff) { i_expiryTime -= diff; }
/**
* @brief
*
* @return bool
*/
bool Passed() const { return (i_expiryTime <= 0); }
/**
* @brief
*
* @param interval
*/
void Reset(int32 interval) { i_expiryTime = interval; }
/**
* @brief
*
* @return int32
*/
int32 GetExpiry() const { return i_expiryTime; }
public:
PeriodicTimer(int32 period, int32 start_time) :
i_period(period), i_expireTime(start_time) { }
private:
int32 i_expiryTime; /**< TODO */
bool Update(const uint32 diff)
{
if ((i_expireTime -= diff) > 0)
{
return false;
}
i_expireTime += i_period > int32(diff) ? i_period : diff;
return true;
}
void SetPeriodic(int32 period, int32 start_time)
{
i_expireTime = start_time;
i_period = period;
}
// Tracker interface
void TUpdate(int32 diff) { i_expireTime -= diff; }
bool TPassed() const { return i_expireTime <= 0; }
void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; }
private:
int32 i_period;
int32 i_expireTime;
};
#endif

View File

@ -27,50 +27,8 @@
#include "utf8.h"
#include "RNGen.h"
#include <ace/TSS_T.h>
#include <ace/INET_Addr.h>
#include "Log/Log.h"
static ACE_Time_Value g_SystemTickTime = ACE_OS::gettimeofday();
uint32 WorldTimer::m_iTime = 0;
uint32 WorldTimer::m_iPrevTime = 0;
uint32 WorldTimer::tickTime() { return m_iTime; }
uint32 WorldTimer::tickPrevTime() { return m_iPrevTime; }
uint32 WorldTimer::tick()
{
// save previous world tick time
m_iPrevTime = m_iTime;
// get the new one and don't forget to persist current system time in m_SystemTickTime
m_iTime = WorldTimer::getMSTime_internal();
// return tick diff
return getMSTimeDiff(m_iPrevTime, m_iTime);
}
uint32 WorldTimer::getMSTime()
{
return getMSTime_internal();
}
uint32 WorldTimer::getMSTime_internal()
{
// get current time
const ACE_Time_Value currTime = ACE_OS::gettimeofday();
// calculate time diff between two world ticks
// special case: curr_time < old_time - we suppose that our time has not ticked at all
// this should be constant value otherwise it is possible that our time can start ticking backwards until next world tick!!!
uint64 diff = 0;
(currTime - g_SystemTickTime).msec(diff);
// lets calculate current world time
uint32 iRes = uint32(diff % UI64LIT(0x00000000FFFFFFFF));
return iRes;
}
//////////////////////////////////////////////////////////////////////////
int32 irand(int32 min, int32 max)
{
@ -194,6 +152,17 @@ void stripLineInvisibleChars(std::string& str)
}
}
std::tm localtime_r(const time_t& time)
{
std::tm tm_snapshot;
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
localtime_s(&tm_snapshot, &time);
#else
localtime_r(&time, &tm_snapshot); // POSIX
#endif
return tm_snapshot;
}
std::string secsToTimeString(time_t timeInSecs, bool shortText, bool hoursOnly)
{
time_t secs = timeInSecs % MINUTE;
@ -259,7 +228,7 @@ uint32 TimeStringToSecs(const std::string& timestring)
std::string TimeToTimestampStr(time_t t)
{
tm* aTm = localtime(&t);
tm aTm = localtime_r(t);
// YYYY year
// MM month (2 digits 01-12)
// DD day (2 digits 01-31)
@ -267,7 +236,7 @@ std::string TimeToTimestampStr(time_t t)
// MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59)
char buf[20];
snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
return std::string(buf);
}

View File

@ -26,7 +26,6 @@
#define MANGOS_H_UTIL
#include "Common/Common.h"
#include <ace/Null_Mutex.h>
#include <ace/INET_Addr.h>
#include <string>
@ -72,6 +71,13 @@ float GetFloatValueFromArray(Tokens const& data, uint16 index);
*/
void stripLineInvisibleChars(std::string& src);
/**
* @brief
*
* @param localtime
*/
std::tm localtime_r(const time_t& time);
/**
* @brief
*