2021-12-05 17:54:36 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// C++
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <random>
|
|
|
|
#include <time.h>
|
|
|
|
#include <string>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <functional>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <BitStream.h>
|
2023-03-25 10:26:39 +00:00
|
|
|
#include "NiPoint3.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
#include "Game.h"
|
2023-10-21 23:31:55 +00:00
|
|
|
#include "Logger.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-12-18 15:46:04 +00:00
|
|
|
enum eInventoryType : uint32_t;
|
2023-04-25 18:17:40 +00:00
|
|
|
enum class eObjectBits : size_t;
|
2023-03-04 07:16:37 +00:00
|
|
|
enum class eReplicaComponentType : uint32_t;
|
2022-12-18 15:46:04 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
/*!
|
|
|
|
\file GeneralUtils.hpp
|
|
|
|
\brief A namespace containing general utility functions
|
|
|
|
*/
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
//! The general utils namespace
|
2021-12-05 17:54:36 +00:00
|
|
|
namespace GeneralUtils {
|
2022-07-28 13:39:57 +00:00
|
|
|
//! Converts a plain ASCII string to a UTF-16 string
|
|
|
|
/*!
|
|
|
|
\param string The string to convert
|
|
|
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
|
|
|
\return An UTF-16 representation of the string
|
|
|
|
*/
|
|
|
|
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
|
|
|
|
|
|
|
|
//! Converts a UTF-8 String to a UTF-16 string
|
|
|
|
/*!
|
|
|
|
\param string The string to convert
|
|
|
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
|
|
|
\return An UTF-16 representation of the string
|
|
|
|
*/
|
|
|
|
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
|
|
|
|
|
|
|
|
//! Internal, do not use
|
|
|
|
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
|
|
|
|
|
|
|
//! Converts a UTF-16 string to a UTF-8 string
|
|
|
|
/*!
|
|
|
|
\param string The string to convert
|
|
|
|
\param size A size to trim the string to. Default is -1 (No trimming)
|
|
|
|
\return An UTF-8 representation of the string
|
|
|
|
*/
|
|
|
|
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compares two basic strings but does so ignoring case sensitivity
|
|
|
|
* \param a the first string to compare against the second string
|
|
|
|
* \param b the second string to compare against the first string
|
|
|
|
* @return if the two strings are equal
|
|
|
|
*/
|
|
|
|
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
|
|
|
|
|
|
|
|
// MARK: Bits
|
|
|
|
|
|
|
|
// MARK: Bits
|
|
|
|
|
|
|
|
//! Sets a bit on a numerical value
|
|
|
|
template <typename T>
|
2023-04-25 18:17:40 +00:00
|
|
|
inline void SetBit(T& value, eObjectBits bits) {
|
2022-07-28 13:39:57 +00:00
|
|
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
2023-04-25 18:17:40 +00:00
|
|
|
auto index = static_cast<size_t>(bits);
|
2022-07-28 13:39:57 +00:00
|
|
|
if (index > (sizeof(T) * 8) - 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
value |= static_cast<T>(1) << index;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Clears a bit on a numerical value
|
|
|
|
template <typename T>
|
2023-04-25 18:17:40 +00:00
|
|
|
inline void ClearBit(T& value, eObjectBits bits) {
|
2022-07-28 13:39:57 +00:00
|
|
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
2023-04-25 18:17:40 +00:00
|
|
|
auto index = static_cast<size_t>(bits);
|
2022-07-28 13:39:57 +00:00
|
|
|
if (index > (sizeof(T) * 8 - 1)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
value &= ~(static_cast<T>(1) << index);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Sets a specific bit in a signed 64-bit integer
|
|
|
|
/*!
|
|
|
|
\param value The value to set the bit for
|
|
|
|
\param index The index of the bit
|
|
|
|
*/
|
|
|
|
int64_t SetBit(int64_t value, uint32_t index);
|
|
|
|
|
|
|
|
//! Clears a specific bit in a signed 64-bit integer
|
|
|
|
/*!
|
|
|
|
\param value The value to clear the bit from
|
|
|
|
\param index The index of the bit
|
|
|
|
*/
|
|
|
|
int64_t ClearBit(int64_t value, uint32_t index);
|
|
|
|
|
|
|
|
//! Checks a specific bit in a signed 64-bit integer
|
|
|
|
/*!
|
|
|
|
\parma value The value to check the bit in
|
|
|
|
\param index The index of the bit
|
|
|
|
\return Whether or not the bit is set
|
|
|
|
*/
|
|
|
|
bool CheckBit(int64_t value, uint32_t index);
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
std::u16string ReadWString(RakNet::BitStream* inStream);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
|
|
|
|
|
2023-04-08 20:45:45 +00:00
|
|
|
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
|
|
|
|
2022-12-05 15:04:59 +00:00
|
|
|
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
T Parse(const char* value);
|
2022-07-10 19:40:26 +00:00
|
|
|
|
2023-10-09 20:22:40 +00:00
|
|
|
template <>
|
|
|
|
inline bool Parse(const char* value) {
|
|
|
|
return std::stoi(value);
|
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
template <>
|
|
|
|
inline int32_t Parse(const char* value) {
|
|
|
|
return std::stoi(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline int64_t Parse(const char* value) {
|
|
|
|
return std::stoll(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline float Parse(const char* value) {
|
|
|
|
return std::stof(value);
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
template <>
|
2022-07-28 13:39:57 +00:00
|
|
|
inline double Parse(const char* value) {
|
|
|
|
return std::stod(value);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-11-18 09:33:23 +00:00
|
|
|
template <>
|
|
|
|
inline uint16_t Parse(const char* value) {
|
|
|
|
return std::stoul(value);
|
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
template <>
|
|
|
|
inline uint32_t Parse(const char* value) {
|
|
|
|
return std::stoul(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline uint64_t Parse(const char* value) {
|
|
|
|
return std::stoull(value);
|
|
|
|
}
|
|
|
|
|
2022-12-18 15:46:04 +00:00
|
|
|
template <>
|
|
|
|
inline eInventoryType Parse(const char* value) {
|
|
|
|
return static_cast<eInventoryType>(std::stoul(value));
|
|
|
|
}
|
|
|
|
|
2023-03-04 07:16:37 +00:00
|
|
|
template <>
|
|
|
|
inline eReplicaComponentType Parse(const char* value) {
|
|
|
|
return static_cast<eReplicaComponentType>(std::stoul(value));
|
|
|
|
}
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
template <typename T>
|
|
|
|
bool TryParse(const char* value, T& dst) {
|
|
|
|
try {
|
|
|
|
dst = Parse<T>(value);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} catch (...) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
T Parse(const std::string& value) {
|
|
|
|
return Parse<T>(value.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
bool TryParse(const std::string& value, T& dst) {
|
|
|
|
return TryParse<T>(value.c_str(), dst);
|
|
|
|
}
|
|
|
|
|
2023-03-25 10:26:39 +00:00
|
|
|
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
|
|
|
|
|
2022-07-28 13:39:57 +00:00
|
|
|
template<typename T>
|
|
|
|
std::u16string to_u16string(T value) {
|
|
|
|
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// From boost::hash_combine
|
|
|
|
template <class T>
|
|
|
|
void hash_combine(std::size_t& s, const T& v) {
|
|
|
|
std::hash<T> h;
|
|
|
|
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
|
|
|
}
|
2023-07-23 21:59:43 +00:00
|
|
|
|
|
|
|
// MARK: Random Number Generation
|
|
|
|
|
|
|
|
//! Generates a random number
|
|
|
|
/*!
|
|
|
|
\param min The minimum the generate from
|
|
|
|
\param max The maximum to generate to
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
|
|
|
// Make sure it is a numeric type
|
|
|
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
|
|
|
|
|
|
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
|
|
|
std::uniform_int_distribution<T> distribution(min, max);
|
|
|
|
return distribution(Game::randomEngine);
|
|
|
|
} else if (std::is_floating_point_v<T>) {
|
|
|
|
std::uniform_real_distribution<T> distribution(min, max);
|
|
|
|
return distribution(Game::randomEngine);
|
|
|
|
}
|
|
|
|
|
|
|
|
return T();
|
|
|
|
}
|
|
|
|
|
|
|
|
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
|
|
|
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
|
|
|
#ifdef _WIN32
|
|
|
|
#undef min
|
|
|
|
#undef max
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline T GenerateRandomNumber() {
|
|
|
|
// Make sure it is a numeric type
|
|
|
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
|
|
|
|
|
|
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|