mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-03 10:53:48 +00:00
[CHORE] Util classes format and simple cleanup with generated resources (#2028)
- Did some basic formatting - Some generated docs - Cleaned header/impl Helper.css - Moved PerfMonitor from util to bot/handler/command Still a freaking mess though, but its a start i guess. Cant ask ppl to add more or make use of those when its so messy.
This commit is contained in:
@@ -5,6 +5,17 @@
|
||||
|
||||
#include "Helpers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Case-insensitive substring search.
|
||||
*/
|
||||
char* strstri(char const* haystack, char const* needle)
|
||||
{
|
||||
if (!*needle)
|
||||
@@ -16,7 +27,9 @@ char* strstri(char const* haystack, char const* needle)
|
||||
{
|
||||
if (tolower(*haystack) == tolower(*needle))
|
||||
{
|
||||
char const *h = haystack, *n = needle;
|
||||
char const* h = haystack;
|
||||
char const* n = needle;
|
||||
|
||||
for (; *h && *n; ++h, ++n)
|
||||
{
|
||||
if (tolower(*h) != tolower(*n))
|
||||
@@ -35,16 +48,67 @@ char* strstri(char const* haystack, char const* needle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace from the left side of a string (in place).
|
||||
*/
|
||||
std::string& ltrim(std::string& s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace from the right side of a string (in place).
|
||||
*/
|
||||
std::string& rtrim(std::string& s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace from both ends of a string (in place).
|
||||
*/
|
||||
std::string& trim(std::string& s) { return ltrim(rtrim(s)); }
|
||||
|
||||
/**
|
||||
* Split a string using a C-string delimiter.
|
||||
*/
|
||||
void split(std::vector<std::string>& dest, std::string const str, char const* delim)
|
||||
{
|
||||
char* pTempStr = strdup(str.c_str());
|
||||
char* pWord = strtok(pTempStr, delim);
|
||||
|
||||
while (pWord != nullptr)
|
||||
{
|
||||
dest.push_back(pWord);
|
||||
pWord = strtok(nullptr, delim);
|
||||
}
|
||||
|
||||
free(pTempStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a string using a single character delimiter.
|
||||
*/
|
||||
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems)
|
||||
{
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
|
||||
while (getline(ss, item, delim))
|
||||
{
|
||||
elems.push_back(item);
|
||||
}
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split a string using a single character delimiter.
|
||||
*/
|
||||
std::vector<std::string> split(std::string const s, char delim)
|
||||
{
|
||||
std::vector<std::string> elems;
|
||||
return split(s, delim, elems);
|
||||
}
|
||||
|
||||
@@ -6,50 +6,68 @@
|
||||
#ifndef _PLAYERBOT_HELPERS_H
|
||||
#define _PLAYERBOT_HELPERS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
/**
|
||||
* Case-insensitive substring search.
|
||||
*
|
||||
* @param haystack The string to search in
|
||||
* @param needle The substring to search for
|
||||
* @return Pointer to the first matching position in haystack, or nullptr if not found.
|
||||
*/
|
||||
char* strstri(char const* haystack, char const* needle);
|
||||
|
||||
void split(std::vector<std::string>& dest, std::string const str, char const* delim)
|
||||
{
|
||||
char* pTempStr = strdup(str.c_str());
|
||||
char* pWord = strtok(pTempStr, delim);
|
||||
/**
|
||||
* Trim whitespace from the left side of a string (in place).
|
||||
*
|
||||
* @param s The string to trim
|
||||
* @return Reference to the modified string
|
||||
*/
|
||||
std::string& ltrim(std::string& s);
|
||||
|
||||
while (pWord != nullptr)
|
||||
{
|
||||
dest.push_back(pWord);
|
||||
pWord = strtok(nullptr, delim);
|
||||
}
|
||||
/**
|
||||
* Trim whitespace from the right side of a string (in place).
|
||||
*
|
||||
* @param s The string to trim
|
||||
* @return Reference to the modified string
|
||||
*/
|
||||
std::string& rtrim(std::string& s);
|
||||
|
||||
free(pTempStr);
|
||||
}
|
||||
/**
|
||||
* Trim whitespace from both ends of a string (in place).
|
||||
*
|
||||
* @param s The string to trim
|
||||
* @return Reference to the modified string
|
||||
*/
|
||||
std::string& trim(std::string& s);
|
||||
|
||||
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems)
|
||||
{
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
/**
|
||||
* Split a string using a C-string delimiter.
|
||||
*
|
||||
* @param dest Vector to store split tokens
|
||||
* @param str String to split
|
||||
* @param delim C-string delimiter
|
||||
*/
|
||||
void split(std::vector<std::string>& dest, std::string const str, char const* delim);
|
||||
|
||||
while (getline(ss, item, delim))
|
||||
{
|
||||
elems.push_back(item);
|
||||
}
|
||||
/**
|
||||
* Split a string using a single character delimiter.
|
||||
*
|
||||
* @param s String to split
|
||||
* @param delim Delimiter character
|
||||
* @param elems Vector to store split tokens
|
||||
* @return Reference to the vector containing tokens
|
||||
*/
|
||||
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems);
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(std::string const s, char delim)
|
||||
{
|
||||
std::vector<std::string> elems;
|
||||
return split(s, delim, elems);
|
||||
}
|
||||
/**
|
||||
* Split a string using a single character delimiter.
|
||||
*
|
||||
* @param s String to split
|
||||
* @param delim Delimiter character
|
||||
* @return Vector containing split tokens
|
||||
*/
|
||||
std::vector<std::string> split(std::string const s, char delim);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,16 +6,45 @@
|
||||
#ifndef _PLAYERBOT_LAZYCALCULATEDVALUE_H
|
||||
#define _PLAYERBOT_LAZYCALCULATEDVALUE_H
|
||||
|
||||
/**
|
||||
* @brief Lazy calculation helper.
|
||||
*
|
||||
* Stores a function pointer (calculator) and its owner instance, and
|
||||
* calculates the value only when it is requested for the first time.
|
||||
* The result is cached until Reset() is called.
|
||||
*
|
||||
* @tparam TValue Type of the calculated value.
|
||||
* @tparam TOwner Type of the owner class containing the calculator function.
|
||||
*/
|
||||
template <class TValue, class TOwner>
|
||||
class LazyCalculatedValue
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Type of the calculator function.
|
||||
*
|
||||
* This is a pointer to a member function of TOwner returning TValue.
|
||||
*/
|
||||
typedef TValue (TOwner::*Calculator)();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param owner Pointer to the owner object.
|
||||
* @param calculator Pointer to the member function used to calculate the value.
|
||||
*/
|
||||
LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner) { Reset(); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the cached value or calculate it if needed.
|
||||
*
|
||||
* If the value has not been calculated yet, it calls the calculator
|
||||
* on the owner and caches the result.
|
||||
*
|
||||
* @return TValue The calculated or cached value.
|
||||
*/
|
||||
TValue GetValue()
|
||||
{
|
||||
if (!calculated)
|
||||
@@ -27,13 +56,19 @@ public:
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the cached state.
|
||||
*
|
||||
* After calling Reset(), the next call to GetValue() will recalculate
|
||||
* the value again.
|
||||
*/
|
||||
void Reset() { calculated = false; }
|
||||
|
||||
protected:
|
||||
Calculator calculator;
|
||||
TOwner* owner;
|
||||
bool calculated;
|
||||
TValue value;
|
||||
Calculator calculator; ///< Pointer to calculator member function
|
||||
TOwner* owner; ///< Owner instance
|
||||
bool calculated; ///< Whether value has already been calculated
|
||||
TValue value; ///< Cached value
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "PerfMonitor.h"
|
||||
|
||||
#include "Playerbots.h"
|
||||
|
||||
PerfMonitorOperation* PerfMonitor::start(PerformanceMetric metric, std::string const name,
|
||||
PerformanceStack* stack)
|
||||
{
|
||||
if (!sPlayerbotAIConfig->perfMonEnabled)
|
||||
return nullptr;
|
||||
|
||||
std::string stackName = name;
|
||||
|
||||
if (stack)
|
||||
{
|
||||
if (!stack->empty())
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << stackName << " [";
|
||||
|
||||
for (std::vector<std::string>::reverse_iterator i = stack->rbegin(); i != stack->rend(); ++i)
|
||||
out << *i << (std::next(i) == stack->rend() ? "" : "|");
|
||||
|
||||
out << "]";
|
||||
|
||||
stackName = out.str().c_str();
|
||||
}
|
||||
|
||||
stack->push_back(name);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> guard(lock);
|
||||
PerformanceData* pd = data[metric][stackName];
|
||||
if (!pd)
|
||||
{
|
||||
pd = new PerformanceData();
|
||||
pd->minTime = 0;
|
||||
pd->maxTime = 0;
|
||||
pd->totalTime = 0;
|
||||
pd->count = 0;
|
||||
data[metric][stackName] = pd;
|
||||
}
|
||||
|
||||
return new PerfMonitorOperation(pd, name, stack);
|
||||
}
|
||||
|
||||
void PerfMonitor::PrintStats(bool perTick, bool fullStack)
|
||||
{
|
||||
if (data.empty())
|
||||
return;
|
||||
|
||||
if (!perTick)
|
||||
{
|
||||
float updateAITotalTime = 0;
|
||||
for (auto& map : data[PERF_MON_TOTAL])
|
||||
if (map.first.find("PlayerbotAI::UpdateAIInternal") != std::string::npos)
|
||||
updateAITotalTime += map.second->totalTime;
|
||||
|
||||
LOG_INFO(
|
||||
"playerbots",
|
||||
"--------------------------------------[TOTAL BOT]------------------------------------------------------");
|
||||
LOG_INFO("playerbots",
|
||||
"percentage time | min .. max ( avg of count) - type : name");
|
||||
LOG_INFO(
|
||||
"playerbots",
|
||||
"-------------------------------------------------------------------------------------------------------");
|
||||
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
|
||||
i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
|
||||
std::string key;
|
||||
switch (i->first)
|
||||
{
|
||||
case PERF_MON_TRIGGER:
|
||||
key = "Trigger";
|
||||
break;
|
||||
case PERF_MON_VALUE:
|
||||
key = "Value";
|
||||
break;
|
||||
case PERF_MON_ACTION:
|
||||
key = "Action";
|
||||
break;
|
||||
case PERF_MON_RNDBOT:
|
||||
key = "RndBot";
|
||||
break;
|
||||
case PERF_MON_TOTAL:
|
||||
key = "Total";
|
||||
break;
|
||||
default:
|
||||
key = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
if (key == "Total" && j->first.find("PlayerbotAI::UpdateAIInternal") == std::string::npos)
|
||||
continue;
|
||||
|
||||
names.push_back(j->first);
|
||||
}
|
||||
|
||||
std::sort(names.begin(), names.end(),
|
||||
[pdMap](std::string const i, std::string const j)
|
||||
{ return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; });
|
||||
|
||||
uint64 typeTotalTime = 0;
|
||||
uint64 typeMinTime = 0xffffffffu;
|
||||
uint64 typeMaxTime = 0;
|
||||
uint32 typeCount = 0;
|
||||
for (auto& name : names)
|
||||
{
|
||||
PerformanceData* pd = pdMap[name];
|
||||
typeTotalTime += pd->totalTime;
|
||||
typeCount += pd->count;
|
||||
if (typeMinTime > pd->minTime)
|
||||
typeMinTime = pd->minTime;
|
||||
if (typeMaxTime < pd->maxTime)
|
||||
typeMaxTime = pd->maxTime;
|
||||
float perc = (float)pd->totalTime / updateAITotalTime * 100.0f;
|
||||
float time = (float)pd->totalTime / 1000000.0f;
|
||||
float minTime = (float)pd->minTime / 1000.0f;
|
||||
float maxTime = (float)pd->maxTime / 1000.0f;
|
||||
float avg = (float)pd->totalTime / (float)pd->count / 1000.0f;
|
||||
std::string disName = name;
|
||||
if (!fullStack && disName.find("|") != std::string::npos)
|
||||
disName = disName.substr(0, disName.find("|")) + "]";
|
||||
|
||||
if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000)
|
||||
{
|
||||
LOG_INFO("playerbots",
|
||||
"{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}", perc, time,
|
||||
minTime, maxTime, avg, pd->count, key.c_str(), disName.c_str());
|
||||
}
|
||||
}
|
||||
float tPerc = (float)typeTotalTime / (float)updateAITotalTime * 100.0f;
|
||||
float tTime = (float)typeTotalTime / 1000000.0f;
|
||||
float tMinTime = (float)typeMinTime / 1000.0f;
|
||||
float tMaxTime = (float)typeMaxTime / 1000.0f;
|
||||
float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f;
|
||||
LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}", tPerc,
|
||||
tTime, tMinTime, tMaxTime, tAvg, typeCount, key.c_str(), "Total");
|
||||
LOG_INFO("playerbots", " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float fullTickCount = data[PERF_MON_TOTAL]["PlayerbotAIBase::FullTick"]->count;
|
||||
float fullTickTotalTime = data[PERF_MON_TOTAL]["PlayerbotAIBase::FullTick"]->totalTime;
|
||||
|
||||
LOG_INFO(
|
||||
"playerbots",
|
||||
"---------------------------------------[PER TICK]------------------------------------------------------");
|
||||
LOG_INFO("playerbots",
|
||||
"percentage time | min .. max ( avg of count) - type : name");
|
||||
LOG_INFO(
|
||||
"playerbots",
|
||||
"-------------------------------------------------------------------------------------------------------");
|
||||
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
|
||||
i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
|
||||
std::string key;
|
||||
switch (i->first)
|
||||
{
|
||||
case PERF_MON_TRIGGER:
|
||||
key = "Trigger";
|
||||
break;
|
||||
case PERF_MON_VALUE:
|
||||
key = "Value";
|
||||
break;
|
||||
case PERF_MON_ACTION:
|
||||
key = "Action";
|
||||
break;
|
||||
case PERF_MON_RNDBOT:
|
||||
key = "RndBot";
|
||||
break;
|
||||
case PERF_MON_TOTAL:
|
||||
key = "Total";
|
||||
break;
|
||||
default:
|
||||
key = "?";
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
names.push_back(j->first);
|
||||
}
|
||||
|
||||
std::sort(names.begin(), names.end(),
|
||||
[pdMap](std::string const i, std::string const j)
|
||||
{ return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; });
|
||||
|
||||
uint64 typeTotalTime = 0;
|
||||
uint64 typeMinTime = 0xffffffffu;
|
||||
uint64 typeMaxTime = 0;
|
||||
uint32 typeCount = 0;
|
||||
for (auto& name : names)
|
||||
{
|
||||
PerformanceData* pd = pdMap[name];
|
||||
typeTotalTime += pd->totalTime;
|
||||
typeCount += pd->count;
|
||||
if (typeMinTime > pd->minTime)
|
||||
typeMinTime = pd->minTime;
|
||||
if (typeMaxTime < pd->maxTime)
|
||||
typeMaxTime = pd->maxTime;
|
||||
float perc = (float)pd->totalTime / fullTickTotalTime * 100.0f;
|
||||
float time = (float)pd->totalTime / fullTickCount / 1000.0f;
|
||||
float minTime = (float)pd->minTime / 1000.0f;
|
||||
float maxTime = (float)pd->maxTime / 1000.0f;
|
||||
float avg = (float)pd->totalTime / (float)pd->count / 1000.0f;
|
||||
float amount = (float)pd->count / fullTickCount;
|
||||
std::string disName = name;
|
||||
if (!fullStack && disName.find("|") != std::string::npos)
|
||||
disName = disName.substr(0, disName.find("|")) + "]";
|
||||
if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000)
|
||||
{
|
||||
LOG_INFO("playerbots",
|
||||
"{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}", perc,
|
||||
time, minTime, maxTime, avg, amount, key.c_str(), disName.c_str());
|
||||
}
|
||||
}
|
||||
if (i->first != PERF_MON_TOTAL)
|
||||
{
|
||||
float tPerc = (float)typeTotalTime / (float)fullTickTotalTime * 100.0f;
|
||||
float tTime = (float)typeTotalTime / fullTickCount / 1000.0f;
|
||||
float tMinTime = (float)typeMinTime / 1000.0f;
|
||||
float tMaxTime = (float)typeMaxTime / 1000.0f;
|
||||
float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f;
|
||||
float tAmount = (float)typeCount / fullTickCount;
|
||||
LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}",
|
||||
tPerc, tTime, tMinTime, tMaxTime, tAvg, tAmount, key.c_str(), "Total");
|
||||
}
|
||||
LOG_INFO("playerbots", " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerfMonitor::Reset()
|
||||
{
|
||||
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
|
||||
i != data.end(); ++i)
|
||||
{
|
||||
std::map<std::string, PerformanceData*> pdMap = i->second;
|
||||
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
|
||||
{
|
||||
PerformanceData* pd = j->second;
|
||||
std::lock_guard<std::mutex> guard(pd->lock);
|
||||
pd->minTime = 0;
|
||||
pd->maxTime = 0;
|
||||
pd->totalTime = 0;
|
||||
pd->count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PerfMonitorOperation::PerfMonitorOperation(PerformanceData* data, std::string const name,
|
||||
PerformanceStack* stack)
|
||||
: data(data), name(name), stack(stack)
|
||||
{
|
||||
started = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()))
|
||||
.time_since_epoch();
|
||||
}
|
||||
|
||||
void PerfMonitorOperation::finish()
|
||||
{
|
||||
std::chrono::microseconds finished =
|
||||
(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()))
|
||||
.time_since_epoch();
|
||||
uint64 elapsed = (finished - started).count();
|
||||
|
||||
std::lock_guard<std::mutex> guard(data->lock);
|
||||
if (elapsed > 0)
|
||||
{
|
||||
if (!data->minTime || data->minTime > elapsed)
|
||||
data->minTime = elapsed;
|
||||
|
||||
if (!data->maxTime || data->maxTime < elapsed)
|
||||
data->maxTime = elapsed;
|
||||
|
||||
data->totalTime += elapsed;
|
||||
}
|
||||
|
||||
++data->count;
|
||||
|
||||
if (stack)
|
||||
{
|
||||
stack->erase(std::remove(stack->begin(), stack->end(), name), stack->end());
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
||||
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_PERFORMANCEMONITOR_H
|
||||
#define _PLAYERBOT_PERFORMANCEMONITOR_H
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
typedef std::vector<std::string> PerformanceStack;
|
||||
|
||||
struct PerformanceData
|
||||
{
|
||||
uint64 minTime;
|
||||
uint64 maxTime;
|
||||
uint64 totalTime;
|
||||
uint32 count;
|
||||
std::mutex lock;
|
||||
};
|
||||
|
||||
enum PerformanceMetric
|
||||
{
|
||||
PERF_MON_TRIGGER,
|
||||
PERF_MON_VALUE,
|
||||
PERF_MON_ACTION,
|
||||
PERF_MON_RNDBOT,
|
||||
PERF_MON_TOTAL
|
||||
};
|
||||
|
||||
class PerfMonitorOperation
|
||||
{
|
||||
public:
|
||||
PerfMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack);
|
||||
void finish();
|
||||
|
||||
private:
|
||||
PerformanceData* data;
|
||||
std::string const name;
|
||||
PerformanceStack* stack;
|
||||
std::chrono::microseconds started;
|
||||
};
|
||||
|
||||
class PerfMonitor
|
||||
{
|
||||
public:
|
||||
PerfMonitor(){};
|
||||
virtual ~PerfMonitor(){};
|
||||
static PerfMonitor* instance()
|
||||
{
|
||||
static PerfMonitor instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
public:
|
||||
PerfMonitorOperation* start(PerformanceMetric metric, std::string const name,
|
||||
PerformanceStack* stack = nullptr);
|
||||
void PrintStats(bool perTick = false, bool fullStack = false);
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
std::map<PerformanceMetric, std::map<std::string, PerformanceData*> > data;
|
||||
std::mutex lock;
|
||||
};
|
||||
|
||||
#define sPerfMonitor PerfMonitor::instance()
|
||||
|
||||
#endif
|
||||
@@ -45,11 +45,13 @@ void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force)
|
||||
return;
|
||||
|
||||
float angle = bot->GetAngle(wo);
|
||||
|
||||
// if (!force && bot->isMoving())
|
||||
// bot->SetFacingTo(bot->GetAngle(wo));
|
||||
// else
|
||||
// {
|
||||
bot->SetOrientation(angle);
|
||||
|
||||
if (!bot->IsRooted())
|
||||
bot->SendMovementFlagUpdate();
|
||||
// }
|
||||
@@ -64,16 +66,14 @@ Unit* ServerFacade::GetChaseTarget(Unit* target)
|
||||
{
|
||||
return static_cast<ChaseMovementGenerator<Player> const*>(movementGen)->GetTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<ChaseMovementGenerator<Creature> const*>(movementGen)->GetTarget();
|
||||
}
|
||||
|
||||
return static_cast<ChaseMovementGenerator<Creature> const*>(movementGen)->GetTarget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ServerFacade::SendPacket(Player *player, WorldPacket *packet)
|
||||
void ServerFacade::SendPacket(Player* player, WorldPacket* packet)
|
||||
{
|
||||
return player->GetSession()->SendPacket(packet);
|
||||
player->GetSession()->SendPacket(packet);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,24 @@ class Unit;
|
||||
class WorldObject;
|
||||
class WorldPacket;
|
||||
|
||||
/**
|
||||
* @brief Provides a simplified interface to server engine operations.
|
||||
*
|
||||
* ServerFacade acts as a wrapper around common server functions used by
|
||||
* the Playerbot system. It centralizes utility methods for distance
|
||||
* calculations, facing, chase target retrieval, and packet sending.
|
||||
*/
|
||||
class ServerFacade
|
||||
{
|
||||
public:
|
||||
ServerFacade(){};
|
||||
virtual ~ServerFacade(){};
|
||||
ServerFacade() {}
|
||||
virtual ~ServerFacade() {}
|
||||
|
||||
/**
|
||||
* @brief Get singleton instance.
|
||||
*
|
||||
* @return ServerFacade* Pointer to the singleton instance.
|
||||
*/
|
||||
static ServerFacade* instance()
|
||||
{
|
||||
static ServerFacade instance;
|
||||
@@ -25,19 +38,92 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get 2D distance between a unit and a world object.
|
||||
*
|
||||
* The result is rounded to one decimal place.
|
||||
*
|
||||
* @param unit Source unit.
|
||||
* @param wo Target world object.
|
||||
* @return float Distance in yards.
|
||||
*/
|
||||
float GetDistance2d(Unit* unit, WorldObject* wo);
|
||||
|
||||
/**
|
||||
* @brief Get 2D distance between a unit and coordinates.
|
||||
*
|
||||
* The result is rounded to one decimal place.
|
||||
*
|
||||
* @param unit Source unit.
|
||||
* @param x Target X coordinate.
|
||||
* @param y Target Y coordinate.
|
||||
* @return float Distance in yards.
|
||||
*/
|
||||
float GetDistance2d(Unit* unit, float x, float y);
|
||||
|
||||
/**
|
||||
* @brief Compare two distances.
|
||||
*
|
||||
* @param dist1 First distance.
|
||||
* @param dist2 Second distance.
|
||||
* @return true if dist1 < dist2.
|
||||
*/
|
||||
bool IsDistanceLessThan(float dist1, float dist2);
|
||||
|
||||
/**
|
||||
* @brief Compare two distances.
|
||||
*
|
||||
* @param dist1 First distance.
|
||||
* @param dist2 Second distance.
|
||||
* @return true if dist1 > dist2.
|
||||
*/
|
||||
bool IsDistanceGreaterThan(float dist1, float dist2);
|
||||
|
||||
/**
|
||||
* @brief Compare two distances.
|
||||
*
|
||||
* @param dist1 First distance.
|
||||
* @param dist2 Second distance.
|
||||
* @return true if dist1 >= dist2.
|
||||
*/
|
||||
bool IsDistanceGreaterOrEqualThan(float dist1, float dist2);
|
||||
|
||||
/**
|
||||
* @brief Compare two distances.
|
||||
*
|
||||
* @param dist1 First distance.
|
||||
* @param dist2 Second distance.
|
||||
* @return true if dist1 <= dist2.
|
||||
*/
|
||||
bool IsDistanceLessOrEqualThan(float dist1, float dist2);
|
||||
|
||||
/**
|
||||
* @brief Set bot facing towards a world object.
|
||||
*
|
||||
* @param bot Player bot to rotate.
|
||||
* @param wo Target world object.
|
||||
* @param force If true, force facing even while moving.
|
||||
*/
|
||||
void SetFacingTo(Player* bot, WorldObject* wo, bool force = false);
|
||||
|
||||
/**
|
||||
* @brief Get the current chase target of a unit.
|
||||
*
|
||||
* @param target Unit that is chasing.
|
||||
* @return Unit* The chase target, or nullptr if not chasing.
|
||||
*/
|
||||
Unit* GetChaseTarget(Unit* target);
|
||||
|
||||
void SendPacket(Player *player, WorldPacket* packet);
|
||||
/**
|
||||
* @brief Send a raw packet to a player.
|
||||
*
|
||||
* @param player Player to receive the packet.
|
||||
* @param packet Packet to send.
|
||||
*/
|
||||
void SendPacket(Player* player, WorldPacket* packet);
|
||||
};
|
||||
|
||||
/** Global singleton accessor. */
|
||||
#define sServerFacade ServerFacade::instance()
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user