Merge branch 'main' into fix_mechs_for_real

This commit is contained in:
David Markowitz 2024-02-16 19:49:13 -08:00
commit d4b1fa8c56
224 changed files with 2180 additions and 2751 deletions

View File

@ -13,7 +13,7 @@ jobs:
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
os: [ windows-2022, ubuntu-22.04, macos-11 ] os: [ windows-2022, ubuntu-22.04, macos-13 ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -25,9 +25,11 @@ jobs:
with: with:
vs-version: '[17,18)' vs-version: '[17,18)'
msbuild-architecture: x64 msbuild-architecture: x64
- name: Install libssl (Mac Only) - name: Install libssl and switch to XCode 15.2 (Mac Only)
if: ${{ matrix.os == 'macos-11' }} if: ${{ matrix.os == 'macos-13' }}
run: brew install openssl@3 run: |
brew install openssl@3
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
- name: cmake - name: cmake
uses: lukka/run-cmake@v10 uses: lukka/run-cmake@v10
with: with:

View File

@ -3,6 +3,7 @@ project(Darkflame)
include(CTest) include(CTest)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file # Read variables from file
@ -244,6 +245,7 @@ set(INCLUDED_DIRECTORIES
"thirdparty/SQLite" "thirdparty/SQLite"
"thirdparty/cpplinq" "thirdparty/cpplinq"
"thirdparty/cpp-httplib" "thirdparty/cpp-httplib"
"thirdparty/MD5"
"tests" "tests"
"tests/dCommonTests" "tests/dCommonTests"
@ -319,7 +321,7 @@ add_subdirectory(dPhysics)
add_subdirectory(dServer) add_subdirectory(dServer)
# Create a list of common libraries shared between all binaries # Create a list of common libraries shared between all binaries
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum") set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum" "MD5")
# Add platform specific common libraries # Add platform specific common libraries
if(UNIX) if(UNIX)

View File

@ -20,7 +20,7 @@
"inherits": "default" "inherits": "default"
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"displayName": "CI configure step for MacOS", "displayName": "CI configure step for MacOS",
"description": "Same as default, Used in GitHub actions workflow", "description": "Same as default, Used in GitHub actions workflow",
"inherits": "default" "inherits": "default"
@ -74,8 +74,8 @@
"jobs": 2 "jobs": 2
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"configurePreset": "ci-macos-11", "configurePreset": "ci-macos-13",
"displayName": "MacOS CI Build", "displayName": "MacOS CI Build",
"description": "This preset is used by the CI build on MacOS", "description": "This preset is used by the CI build on MacOS",
"jobs": 2 "jobs": 2
@ -95,8 +95,8 @@
} }
}, },
{ {
"name": "ci-macos-11", "name": "ci-macos-13",
"configurePreset": "ci-macos-11", "configurePreset": "ci-macos-13",
"displayName": "CI Tests on MacOS", "displayName": "CI Tests on MacOS",
"description": "Runs all tests on a Mac configuration", "description": "Runs all tests on a Mac configuration",
"execution": { "execution": {

View File

@ -356,6 +356,10 @@ The Darkflame Server is automatically built and published as a Docker Container
## Compose ## Compose
> [!WARNING]
> It seems that Docker Desktop on Windows with the WSL 2 backend has some issues with MariaDB (c.f. [mariadb-docker#331](https://github.com/MariaDB/mariadb-docker/issues/331)) triggered by NexusDashboard
> migrations, so this setup may not work for you. If that is the case, please tell us about your setup in [NexusDashboard#92](https://github.com/DarkflameUniverse/NexusDashboard/issues/92).
You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all You can use the `docker-compose` tool to [setup a MariaDB database](#database-setup), run the Darkflame Server and manage it with [Nexus Dashboard](https://github.com/DarkflameUniverse/NexusDashboard) all
at once. For that: at once. For that:

View File

@ -82,11 +82,11 @@ int main(int argc, char** argv) {
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("auth_server_port"), ourPort);
//LU client is hardcoded to use this for auth port, so I'm making it the default.
const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("auth_server_port")).value_or(1001);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;

View File

@ -99,18 +99,15 @@ int main(int argc, char** argv) {
masterPort = masterInfo->port; masterPort = masterInfo->port;
} }
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 999;
uint32_t ourPort = 1501;
std::string ourIP = "localhost"; std::string ourIP = "localhost";
GeneralUtils::TryParse(Game::config->GetValue("max_clients"), maxClients); const uint32_t maxClients = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_clients")).value_or(999);
GeneralUtils::TryParse(Game::config->GetValue("chat_server_port"), ourPort); const uint32_t ourPort = GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("chat_server_port")).value_or(1501);
const auto externalIPString = Game::config->GetValue("external_ip"); const auto externalIPString = Game::config->GetValue("external_ip");
if (!externalIPString.empty()) ourIP = externalIPString; if (!externalIPString.empty()) ourIP = externalIPString;
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal); Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
bool dontGenerateDCF = false; const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
GeneralUtils::TryParse(Game::config->GetValue("dont_generate_dcf"), dontGenerateDCF);
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
Game::randomEngine = std::mt19937(time(0)); Game::randomEngine = std::mt19937(time(0));

View File

@ -10,21 +10,14 @@
#include "Database.h" #include "Database.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatInternalMessageType.h" #include "eChatInternalMessageType.h"
#include "eGameMasterLevel.h"
#include "ChatPackets.h" #include "ChatPackets.h"
#include "dConfig.h" #include "dConfig.h"
void PlayerContainer::Initialize() { void PlayerContainer::Initialize() {
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends"), m_MaxNumberOfBestFriends); m_MaxNumberOfBestFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends"), m_MaxNumberOfFriends); GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends")).value_or(m_MaxNumberOfBestFriends);
} m_MaxNumberOfFriends =
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends")).value_or(m_MaxNumberOfFriends);
PlayerContainer::~PlayerContainer() {
m_Players.clear();
}
PlayerData::PlayerData() {
gmLevel = eGameMasterLevel::CIVILIAN;
} }
TeamData::TeamData() { TeamData::TeamData() {

View File

@ -10,7 +10,7 @@
enum class eGameMasterLevel : uint8_t; enum class eGameMasterLevel : uint8_t;
struct IgnoreData { struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {} IgnoreData(const std::string& name, const LWOOBJID& id) : playerName{ name }, playerId{ id } {}
inline bool operator==(const std::string& other) const noexcept { inline bool operator==(const std::string& other) const noexcept {
return playerName == other; return playerName == other;
} }
@ -24,7 +24,6 @@ struct IgnoreData {
}; };
struct PlayerData { struct PlayerData {
PlayerData();
operator bool() const noexcept { operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY; return playerID != LWOOBJID_EMPTY;
} }
@ -45,7 +44,7 @@ struct PlayerData {
std::string playerName; std::string playerName;
std::vector<FriendData> friends; std::vector<FriendData> friends;
std::vector<IgnoreData> ignoredPlayers; std::vector<IgnoreData> ignoredPlayers;
eGameMasterLevel gmLevel; eGameMasterLevel gmLevel = static_cast<eGameMasterLevel>(0); // CIVILLIAN
bool isFTP = false; bool isFTP = false;
}; };
@ -61,8 +60,6 @@ struct TeamData {
class PlayerContainer { class PlayerContainer {
public: public:
~PlayerContainer();
void Initialize(); void Initialize();
void InsertPlayer(Packet* packet); void InsertPlayer(Packet* packet);
void RemovePlayer(Packet* packet); void RemovePlayer(Packet* packet);

View File

@ -31,54 +31,68 @@ enum class eAmf : uint8_t {
class AMFBaseValue { class AMFBaseValue {
public: public:
virtual eAmf GetValueType() { return eAmf::Undefined; }; [[nodiscard]] constexpr virtual eAmf GetValueType() const noexcept { return eAmf::Undefined; }
AMFBaseValue() {}; constexpr AMFBaseValue() noexcept = default;
virtual ~AMFBaseValue() {}; constexpr virtual ~AMFBaseValue() noexcept = default;
}; };
template<typename ValueType> // AMFValue template class instantiations
template <typename ValueType>
class AMFValue : public AMFBaseValue { class AMFValue : public AMFBaseValue {
public: public:
AMFValue() {}; AMFValue() = default;
AMFValue(ValueType value) { SetValue(value); }; AMFValue(const ValueType value) { m_Data = value; }
virtual ~AMFValue() override {}; virtual ~AMFValue() override = default;
eAmf GetValueType() override { return eAmf::Undefined; }; [[nodiscard]] constexpr eAmf GetValueType() const noexcept override;
[[nodiscard]] const ValueType& GetValue() const { return m_Data; }
void SetValue(const ValueType value) { m_Data = value; }
const ValueType& GetValue() { return data; };
void SetValue(ValueType value) { data = value; };
protected: protected:
ValueType data; ValueType m_Data;
}; };
// Explicit template class instantiations
template class AMFValue<std::nullptr_t>;
template class AMFValue<bool>;
template class AMFValue<int32_t>;
template class AMFValue<uint32_t>;
template class AMFValue<std::string>;
template class AMFValue<double>;
// AMFValue template class member function instantiations
template <> [[nodiscard]] constexpr eAmf AMFValue<std::nullptr_t>::GetValueType() const noexcept { return eAmf::Null; }
template <> [[nodiscard]] constexpr eAmf AMFValue<bool>::GetValueType() const noexcept { return m_Data ? eAmf::True : eAmf::False; }
template <> [[nodiscard]] constexpr eAmf AMFValue<int32_t>::GetValueType() const noexcept { return eAmf::Integer; }
template <> [[nodiscard]] constexpr eAmf AMFValue<uint32_t>::GetValueType() const noexcept { return eAmf::Integer; }
template <> [[nodiscard]] constexpr eAmf AMFValue<std::string>::GetValueType() const noexcept { return eAmf::String; }
template <> [[nodiscard]] constexpr eAmf AMFValue<double>::GetValueType() const noexcept { return eAmf::Double; }
template <typename ValueType>
[[nodiscard]] constexpr eAmf AMFValue<ValueType>::GetValueType() const noexcept { return eAmf::Undefined; }
// As a string this is much easier to write and read from a BitStream. // As a string this is much easier to write and read from a BitStream.
template<> template <>
class AMFValue<const char*> : public AMFBaseValue { class AMFValue<const char*> : public AMFBaseValue {
public: public:
AMFValue() {}; AMFValue() = default;
AMFValue(const char* value) { SetValue(std::string(value)); }; AMFValue(const char* value) { m_Data = value; }
virtual ~AMFValue() override {}; virtual ~AMFValue() override = default;
eAmf GetValueType() override { return eAmf::String; }; [[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::String; }
const std::string& GetValue() { return data; }; [[nodiscard]] const std::string& GetValue() const { return m_Data; }
void SetValue(std::string value) { data = value; }; void SetValue(const std::string& value) { m_Data = value; }
protected: protected:
std::string data; std::string m_Data;
}; };
typedef AMFValue<std::nullptr_t> AMFNullValue; using AMFNullValue = AMFValue<std::nullptr_t>;
typedef AMFValue<bool> AMFBoolValue; using AMFBoolValue = AMFValue<bool>;
typedef AMFValue<int32_t> AMFIntValue; using AMFIntValue = AMFValue<int32_t>;
typedef AMFValue<std::string> AMFStringValue; using AMFStringValue = AMFValue<std::string>;
typedef AMFValue<double> AMFDoubleValue; using AMFDoubleValue = AMFValue<double>;
template<> inline eAmf AMFValue<std::nullptr_t>::GetValueType() { return eAmf::Null; };
template<> inline eAmf AMFValue<bool>::GetValueType() { return this->data ? eAmf::True : eAmf::False; };
template<> inline eAmf AMFValue<int32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<uint32_t>::GetValueType() { return eAmf::Integer; };
template<> inline eAmf AMFValue<std::string>::GetValueType() { return eAmf::String; };
template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; };
/** /**
* The AMFArrayValue object holds 2 types of lists: * The AMFArrayValue object holds 2 types of lists:
@ -89,12 +103,11 @@ template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; }
* and are not to be deleted by a caller. * and are not to be deleted by a caller.
*/ */
class AMFArrayValue : public AMFBaseValue { class AMFArrayValue : public AMFBaseValue {
using AMFAssociative = std::unordered_map<std::string, AMFBaseValue*>;
typedef std::unordered_map<std::string, AMFBaseValue*> AMFAssociative; using AMFDense = std::vector<AMFBaseValue*>;
typedef std::vector<AMFBaseValue*> AMFDense;
public: public:
eAmf GetValueType() override { return eAmf::Array; }; [[nodiscard]] constexpr eAmf GetValueType() const noexcept override { return eAmf::Array; }
~AMFArrayValue() override { ~AMFArrayValue() override {
for (auto valueToDelete : GetDense()) { for (auto valueToDelete : GetDense()) {
@ -109,17 +122,17 @@ public:
valueToDelete.second = nullptr; valueToDelete.second = nullptr;
} }
} }
}; }
/** /**
* Returns the Associative portion of the object * Returns the Associative portion of the object
*/ */
inline AMFAssociative& GetAssociative() { return this->associative; }; [[nodiscard]] inline AMFAssociative& GetAssociative() noexcept { return this->associative; }
/** /**
* Returns the dense portion of the object * Returns the dense portion of the object
*/ */
inline AMFDense& GetDense() { return this->dense; }; [[nodiscard]] inline AMFDense& GetDense() noexcept { return this->dense; }
/** /**
* Inserts an AMFValue into the associative portion with the given key. * Inserts an AMFValue into the associative portion with the given key.
@ -135,8 +148,8 @@ public:
* @return The inserted element if the type matched, * @return The inserted element if the type matched,
* or nullptr if a key existed and was not the same type * or nullptr if a key existed and was not the same type
*/ */
template<typename ValueType> template <typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, ValueType value) { [[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, const ValueType value) {
auto element = associative.find(key); auto element = associative.find(key);
AMFValue<ValueType>* val = nullptr; AMFValue<ValueType>* val = nullptr;
bool found = true; bool found = true;
@ -148,10 +161,10 @@ public:
found = false; found = false;
} }
return std::make_pair(val, found); return std::make_pair(val, found);
}; }
// Associates an array with a string key // Associates an array with a string key
std::pair<AMFBaseValue*, bool> Insert(const std::string& key) { [[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
auto element = associative.find(key); auto element = associative.find(key);
AMFArrayValue* val = nullptr; AMFArrayValue* val = nullptr;
bool found = true; bool found = true;
@ -163,10 +176,10 @@ public:
found = false; found = false;
} }
return std::make_pair(val, found); return std::make_pair(val, found);
}; }
// Associates an array with an integer key // Associates an array with an integer key
std::pair<AMFBaseValue*, bool> Insert(const uint32_t& index) { [[maybe_unused]] std::pair<AMFBaseValue*, bool> Insert(const size_t index) {
AMFArrayValue* val = nullptr; AMFArrayValue* val = nullptr;
bool inserted = false; bool inserted = false;
if (index >= dense.size()) { if (index >= dense.size()) {
@ -176,7 +189,7 @@ public:
inserted = true; inserted = true;
} }
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted); return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted);
}; }
/** /**
* @brief Inserts an AMFValue into the AMFArray key'd by index. * @brief Inserts an AMFValue into the AMFArray key'd by index.
@ -188,8 +201,8 @@ public:
* @return The inserted element, or nullptr if the type did not match * @return The inserted element, or nullptr if the type did not match
* what was at the index. * what was at the index.
*/ */
template<typename ValueType> template <typename ValueType>
std::pair<AMFValue<ValueType>*, bool> Insert(const uint32_t& index, ValueType value) { [[maybe_unused]] std::pair<AMFValue<ValueType>*, bool> Insert(const size_t index, const ValueType value) {
AMFValue<ValueType>* val = nullptr; AMFValue<ValueType>* val = nullptr;
bool inserted = false; bool inserted = false;
if (index >= this->dense.size()) { if (index >= this->dense.size()) {
@ -199,7 +212,7 @@ public:
inserted = true; inserted = true;
} }
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted); return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted);
}; }
/** /**
* Inserts an AMFValue into the associative portion with the given key. * Inserts an AMFValue into the associative portion with the given key.
@ -210,7 +223,7 @@ public:
* @param key The key to associate with the value * @param key The key to associate with the value
* @param value The value to insert * @param value The value to insert
*/ */
void Insert(const std::string& key, AMFBaseValue* value) { void Insert(const std::string& key, AMFBaseValue* const value) {
auto element = associative.find(key); auto element = associative.find(key);
if (element != associative.end() && element->second) { if (element != associative.end() && element->second) {
delete element->second; delete element->second;
@ -218,7 +231,7 @@ public:
} else { } else {
associative.insert(std::make_pair(key, value)); associative.insert(std::make_pair(key, value));
} }
}; }
/** /**
* Inserts an AMFValue into the associative portion with the given index. * Inserts an AMFValue into the associative portion with the given index.
@ -229,7 +242,7 @@ public:
* @param key The key to associate with the value * @param key The key to associate with the value
* @param value The value to insert * @param value The value to insert
*/ */
void Insert(const uint32_t index, AMFBaseValue* value) { void Insert(const size_t index, AMFBaseValue* const value) {
if (index < dense.size()) { if (index < dense.size()) {
AMFDense::iterator itr = dense.begin() + index; AMFDense::iterator itr = dense.begin() + index;
if (*itr) delete dense.at(index); if (*itr) delete dense.at(index);
@ -237,7 +250,7 @@ public:
dense.resize(index + 1); dense.resize(index + 1);
} }
dense.at(index) = value; dense.at(index) = value;
}; }
/** /**
* Pushes an AMFValue into the back of the dense portion. * Pushes an AMFValue into the back of the dense portion.
@ -249,10 +262,10 @@ public:
* *
* @return The inserted pointer, or nullptr should the key already be in use. * @return The inserted pointer, or nullptr should the key already be in use.
*/ */
template<typename ValueType> template <typename ValueType>
inline AMFValue<ValueType>* Push(ValueType value) { [[maybe_unused]] inline AMFValue<ValueType>* Push(const ValueType value) {
return Insert(this->dense.size(), value).first; return Insert(this->dense.size(), value).first;
}; }
/** /**
* Removes the key from the associative portion * Removes the key from the associative portion
@ -261,7 +274,7 @@ public:
* *
* @param key The key to remove from the associative portion * @param key The key to remove from the associative portion
*/ */
void Remove(const std::string& key, bool deleteValue = true) { void Remove(const std::string& key, const bool deleteValue = true) {
AMFAssociative::iterator it = this->associative.find(key); AMFAssociative::iterator it = this->associative.find(key);
if (it != this->associative.end()) { if (it != this->associative.end()) {
if (deleteValue) delete it->second; if (deleteValue) delete it->second;
@ -272,7 +285,7 @@ public:
/** /**
* Pops the last element in the dense portion, deleting it in the process. * Pops the last element in the dense portion, deleting it in the process.
*/ */
void Remove(const uint32_t index) { void Remove(const size_t index) {
if (!this->dense.empty() && index < this->dense.size()) { if (!this->dense.empty() && index < this->dense.size()) {
auto itr = this->dense.begin() + index; auto itr = this->dense.begin() + index;
if (*itr) delete (*itr); if (*itr) delete (*itr);
@ -284,29 +297,29 @@ public:
if (!this->dense.empty()) Remove(this->dense.size() - 1); if (!this->dense.empty()) Remove(this->dense.size() - 1);
} }
AMFArrayValue* GetArray(const std::string& key) { [[nodiscard]] AMFArrayValue* GetArray(const std::string& key) {
AMFAssociative::const_iterator it = this->associative.find(key); AMFAssociative::const_iterator it = this->associative.find(key);
if (it != this->associative.end()) { if (it != this->associative.end()) {
return dynamic_cast<AMFArrayValue*>(it->second); return dynamic_cast<AMFArrayValue*>(it->second);
} }
return nullptr; return nullptr;
}; }
AMFArrayValue* GetArray(const uint32_t index) { [[nodiscard]] AMFArrayValue* GetArray(const size_t index) {
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index)); return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index));
}; }
inline AMFArrayValue* InsertArray(const std::string& key) { [[maybe_unused]] inline AMFArrayValue* InsertArray(const std::string& key) {
return static_cast<AMFArrayValue*>(Insert(key).first); return static_cast<AMFArrayValue*>(Insert(key).first);
}; }
inline AMFArrayValue* InsertArray(const uint32_t index) { [[maybe_unused]] inline AMFArrayValue* InsertArray(const size_t index) {
return static_cast<AMFArrayValue*>(Insert(index).first); return static_cast<AMFArrayValue*>(Insert(index).first);
}; }
inline AMFArrayValue* PushArray() { [[maybe_unused]] inline AMFArrayValue* PushArray() {
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first); return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first);
}; }
/** /**
* Gets an AMFValue by the key from the associative portion and converts it * Gets an AMFValue by the key from the associative portion and converts it
@ -318,18 +331,18 @@ public:
* @return The AMFValue * @return The AMFValue
*/ */
template <typename AmfType> template <typename AmfType>
AMFValue<AmfType>* Get(const std::string& key) const { [[nodiscard]] AMFValue<AmfType>* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key); AMFAssociative::const_iterator it = this->associative.find(key);
return it != this->associative.end() ? return it != this->associative.end() ?
dynamic_cast<AMFValue<AmfType>*>(it->second) : dynamic_cast<AMFValue<AmfType>*>(it->second) :
nullptr; nullptr;
}; }
// Get from the array but dont cast it // Get from the array but dont cast it
AMFBaseValue* Get(const std::string& key) const { [[nodiscard]] AMFBaseValue* Get(const std::string& key) const {
AMFAssociative::const_iterator it = this->associative.find(key); AMFAssociative::const_iterator it = this->associative.find(key);
return it != this->associative.end() ? it->second : nullptr; return it != this->associative.end() ? it->second : nullptr;
}; }
/** /**
* @brief Get an AMFValue object at a position in the dense portion. * @brief Get an AMFValue object at a position in the dense portion.
@ -341,16 +354,17 @@ public:
* @return The casted object, or nullptr. * @return The casted object, or nullptr.
*/ */
template <typename AmfType> template <typename AmfType>
AMFValue<AmfType>* Get(uint32_t index) const { [[nodiscard]] AMFValue<AmfType>* Get(const size_t index) const {
return index < this->dense.size() ? return index < this->dense.size() ?
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) : dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) :
nullptr; nullptr;
}; }
// Get from the dense but dont cast it // Get from the dense but dont cast it
AMFBaseValue* Get(const uint32_t index) const { [[nodiscard]] AMFBaseValue* Get(const size_t index) const {
return index < this->dense.size() ? this->dense.at(index) : nullptr; return index < this->dense.size() ? this->dense.at(index) : nullptr;
}; }
private: private:
/** /**
* The associative portion. These values are key'd with strings to an AMFValue. * The associative portion. These values are key'd with strings to an AMFValue.

View File

@ -8,11 +8,9 @@ set(DCOMMON_SOURCES
"Game.cpp" "Game.cpp"
"GeneralUtils.cpp" "GeneralUtils.cpp"
"LDFFormat.cpp" "LDFFormat.cpp"
"MD5.cpp"
"Metrics.cpp" "Metrics.cpp"
"NiPoint3.cpp" "NiPoint3.cpp"
"NiQuaternion.cpp" "NiQuaternion.cpp"
"SHA512.cpp"
"Demangler.cpp" "Demangler.cpp"
"ZCompression.cpp" "ZCompression.cpp"
"BrickByBrickFix.cpp" "BrickByBrickFix.cpp"

View File

@ -319,7 +319,3 @@ std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::stri
return sortedFiles; return sortedFiles;
} }
bool GeneralUtils::TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst) {
return TryParse<float>(x.c_str(), dst.x) && TryParse<float>(y.c_str(), dst.y) && TryParse<float>(z.c_str(), dst.z);
}

View File

@ -1,17 +1,20 @@
#pragma once #pragma once
// C++ // C++
#include <stdint.h> #include <charconv>
#include <cstdint>
#include <random> #include <random>
#include <time.h> #include <ctime>
#include <string> #include <string>
#include <type_traits> #include <string_view>
#include <optional>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include <stdexcept> #include <stdexcept>
#include "BitStream.h" #include "BitStream.h"
#include "NiPoint3.h" #include "NiPoint3.h"
#include "dPlatforms.h"
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
@ -123,90 +126,125 @@ namespace GeneralUtils {
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder); std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
// Concept constraining to enum types
template <typename T> template <typename T>
T Parse(const char* value); concept Enum = std::is_enum_v<T>;
template <>
inline bool Parse(const char* value) {
return std::stoi(value);
}
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);
}
template <>
inline double Parse(const char* value) {
return std::stod(value);
}
template <>
inline uint16_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint32_t Parse(const char* value) {
return std::stoul(value);
}
template <>
inline uint64_t Parse(const char* value) {
return std::stoull(value);
}
template <>
inline eInventoryType Parse(const char* value) {
return static_cast<eInventoryType>(std::stoul(value));
}
template <>
inline eReplicaComponentType Parse(const char* value) {
return static_cast<eReplicaComponentType>(std::stoul(value));
}
// Concept constraining to numeric types
template <typename T> template <typename T>
bool TryParse(const char* value, T& dst) { concept Numeric = std::integral<T> || Enum<T> || std::floating_point<T>;
try {
dst = Parse<T>(value);
return true; // Concept trickery to enable parsing underlying numeric types
template <Numeric T>
struct numeric_parse { using type = T; };
// If an enum, present an alias to its underlying type for parsing
template <Numeric T> requires Enum<T>
struct numeric_parse<T> { using type = std::underlying_type_t<T>; };
// If a boolean, present an alias to an intermediate integral type for parsing
template <Numeric T> requires std::same_as<T, bool>
struct numeric_parse<T> { using type = uint32_t; };
// Shorthand type alias
template <Numeric T>
using numeric_parse_t = numeric_parse<T>::type;
/**
* For numeric values: Parses a string_view and returns an optional variable depending on the result.
* @param str The string_view to be evaluated
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
numeric_parse_t<T> result;
const char* const strEnd = str.data() + str.size();
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
const bool isParsed = parseEnd == strEnd && ec == std::errc{};
return isParsed ? static_cast<T>(result) : std::optional<T>{};
}
#ifdef DARKFLAME_PLATFORM_MACOS
// Anonymous namespace containing MacOS floating-point parse function specializations
namespace {
template <std::floating_point T>
[[nodiscard]] T Parse(const std::string_view str, size_t* parseNum);
template <>
[[nodiscard]] float Parse<float>(const std::string_view str, size_t* parseNum) {
return std::stof(std::string{ str }, parseNum);
}
template <>
[[nodiscard]] double Parse<double>(const std::string_view str, size_t* parseNum) {
return std::stod(std::string{ str }, parseNum);
}
template <>
[[nodiscard]] long double Parse<long double>(const std::string_view str, size_t* parseNum) {
return std::stold(std::string{ str }, parseNum);
}
}
/**
* For floating-point values: Parses a string_view and returns an optional variable depending on the result.
* Note that this function overload is only included for MacOS, as from_chars will fulfill its purpose otherwise.
* @param str The string_view to be evaluated
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept try {
size_t parseNum;
const T result = Parse<T>(str, &parseNum);
const bool isParsed = str.length() == parseNum;
return isParsed ? result : std::optional<T>{};
} catch (...) { } catch (...) {
return false; return std::nullopt;
} }
#endif
/**
* The TryParse overload for handling NiPoint3 by passing 3 seperate string references
* @param strX The string representing the X coordinate
* @param strY The string representing the Y coordinate
* @param strZ The string representing the Z coordinate
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
const auto x = TryParse<float>(strX);
if (!x) return std::nullopt;
const auto y = TryParse<float>(strY);
if (!y) return std::nullopt;
const auto z = TryParse<float>(strZ);
return z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
}
/**
* The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
* @param str The string vector representing the X, Y, and Xcoordinates
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
*/
template <typename T>
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
} }
template <typename T> 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);
}
bool TryParse(const std::string& x, const std::string& y, const std::string& z, NiPoint3& dst);
template<typename T>
std::u16string to_u16string(T value) { std::u16string to_u16string(T value) {
return GeneralUtils::ASCIIToUTF16(std::to_string(value)); return GeneralUtils::ASCIIToUTF16(std::to_string(value));
} }
// From boost::hash_combine // From boost::hash_combine
template <class T> template <class T>
void hash_combine(std::size_t& s, const T& v) { constexpr void hash_combine(std::size_t& s, const T& v) {
std::hash<T> h; std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
} }
@ -239,10 +277,8 @@ namespace GeneralUtils {
* @param entry Enum entry to cast * @param entry Enum entry to cast
* @returns The enum entry's value in its underlying type * @returns The enum entry's value in its underlying type
*/ */
template <typename eType> template <Enum eType>
inline constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) { constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) noexcept {
static_assert(std::is_enum_v<eType>, "Not an enum");
return static_cast<typename std::underlying_type_t<eType>>(entry); return static_cast<typename std::underlying_type_t<eType>>(entry);
} }

View File

@ -61,33 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_S32: { case LDF_TYPE_S32: {
int32_t data; const auto data = GeneralUtils::TryParse<int32_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<int32_t>(key, data); returnValue = new LDFData<int32_t>(key, data.value());
break; break;
} }
case LDF_TYPE_FLOAT: { case LDF_TYPE_FLOAT: {
float data; const auto data = GeneralUtils::TryParse<float>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<float>(key, data); returnValue = new LDFData<float>(key, data.value());
break; break;
} }
case LDF_TYPE_DOUBLE: { case LDF_TYPE_DOUBLE: {
double data; const auto data = GeneralUtils::TryParse<double>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<double>(key, data); returnValue = new LDFData<double>(key, data.value());
break; break;
} }
@ -100,10 +100,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = 0; data = 0;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<uint32_t>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<uint32_t>(key, data); returnValue = new LDFData<uint32_t>(key, data);
@ -118,10 +120,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} else if (ldfTypeAndValue.second == "false") { } else if (ldfTypeAndValue.second == "false") {
data = false; data = false;
} else { } else {
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { const auto dataOptional = GeneralUtils::TryParse<bool>(ldfTypeAndValue.second);
if (!dataOptional) {
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
data = dataOptional.value();
} }
returnValue = new LDFData<bool>(key, data); returnValue = new LDFData<bool>(key, data);
@ -129,22 +133,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
} }
case LDF_TYPE_U64: { case LDF_TYPE_U64: {
uint64_t data; const auto data = GeneralUtils::TryParse<uint64_t>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<uint64_t>(key, data); returnValue = new LDFData<uint64_t>(key, data.value());
break; break;
} }
case LDF_TYPE_OBJID: { case LDF_TYPE_OBJID: {
LWOOBJID data; const auto data = GeneralUtils::TryParse<LWOOBJID>(ldfTypeAndValue.second);
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) { if (!data) {
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data()); LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
return nullptr; return nullptr;
} }
returnValue = new LDFData<LWOOBJID>(key, data); returnValue = new LDFData<LWOOBJID>(key, data.value());
break; break;
} }

View File

@ -162,7 +162,7 @@ public:
return new LDFData<T>(key, value); return new LDFData<T>(key, value);
} }
inline static T Default = {}; inline static const T Default = {};
}; };
// LDF Types // LDF Types

View File

@ -1,210 +1,24 @@
#include "NiPoint3.h" #include "NiPoint3.h"
#include "NiQuaternion.h"
// C++ // C++
#include <cmath> #include <cmath>
// Static Variables // MARK: Member Functions
const NiPoint3 NiPoint3::ZERO(0.0f, 0.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_X(1.0f, 0.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_Y(0.0f, 1.0f, 0.0f);
const NiPoint3 NiPoint3::UNIT_Z(0.0f, 0.0f, 1.0f);
const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f);
//! Initializer
NiPoint3::NiPoint3(void) {
this->x = 0;
this->y = 0;
this->z = 0;
}
//! Initializer
NiPoint3::NiPoint3(float x, float y, float z) {
this->x = x;
this->y = y;
this->z = z;
}
//! Copy Constructor
NiPoint3::NiPoint3(const NiPoint3& point) {
this->x = point.x;
this->y = point.y;
this->z = point.z;
}
//! Destructor
NiPoint3::~NiPoint3(void) {}
// MARK: Getters / Setters
//! Gets the X coordinate
float NiPoint3::GetX(void) const {
return this->x;
}
//! Sets the X coordinate
void NiPoint3::SetX(float x) {
this->x = x;
}
//! Gets the Y coordinate
float NiPoint3::GetY(void) const {
return this->y;
}
//! Sets the Y coordinate
void NiPoint3::SetY(float y) {
this->y = y;
}
//! Gets the Z coordinate
float NiPoint3::GetZ(void) const {
return this->z;
}
//! Sets the Z coordinate
void NiPoint3::SetZ(float z) {
this->z = z;
}
// MARK: Functions
//! Gets the length of the vector //! Gets the length of the vector
float NiPoint3::Length(void) const { float NiPoint3::Length() const {
return sqrt(x * x + y * y + z * z); return std::sqrt(x * x + y * y + z * z);
}
//! Gets the squared length of a vector
float NiPoint3::SquaredLength(void) const {
return (x * x + y * y + z * z);
}
//! Returns the dot product of the vector dotted with another vector
float NiPoint3::DotProduct(const Vector3& vec) const {
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
}
//! Returns the cross product of the vector crossed with another vector
Vector3 NiPoint3::CrossProduct(const Vector3& vec) const {
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
} }
//! Unitize the vector //! Unitize the vector
NiPoint3 NiPoint3::Unitize(void) const { NiPoint3 NiPoint3::Unitize() const {
float length = this->Length(); float length = this->Length();
return length != 0 ? *this / length : NiPoint3::ZERO; return length != 0 ? *this / length : NiPoint3Constant::ZERO;
} }
// MARK: Operators
//! Operator to check for equality
bool NiPoint3::operator==(const NiPoint3& point) const {
return point.x == this->x && point.y == this->y && point.z == this->z;
}
//! Operator to check for inequality
bool NiPoint3::operator!=(const NiPoint3& point) const {
return !(*this == point);
}
//! Operator for subscripting
float& NiPoint3::operator[](int i) {
float* base = &x;
return base[i];
}
//! Operator for subscripting
const float& NiPoint3::operator[](int i) const {
const float* base = &x;
return base[i];
}
//! Operator for addition of vectors
NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
}
//! Operator for addition of vectors
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
}
NiPoint3& NiPoint3::operator*=(const float scalar) {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
}
//! Operator for addition of a scalar on all vector components
NiPoint3 NiPoint3::operator+(float fScalar) const {
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
}
//! Operator for subtraction of a scalar on all vector components
NiPoint3 NiPoint3::operator-(float fScalar) const {
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
}
//! Operator for scalar multiplication of a vector
NiPoint3 NiPoint3::operator*(float fScalar) const {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}
//! Operator for scalar division of a vector
NiPoint3 NiPoint3::operator/(float fScalar) const {
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
}
// MARK: Helper Functions // MARK: Helper Functions
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) {
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
return (this->z < maxPoint.z && this->z > minPoint.z);
}
//! Checks to see if the point (or vector) is within a sphere
bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) {
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
}
NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) {
if (a == b) return a;
const auto pa = p - a;
const auto ab = b - a;
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
}
float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) { float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) {
const auto dot = a.DotProduct(b); const auto dot = a.DotProduct(b);
const auto lenA = a.SquaredLength(); const auto lenA = a.SquaredLength();
@ -220,15 +34,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) {
return std::sqrt(dx * dx + dy * dy + dz * dz); return std::sqrt(dx * dx + dy * dy + dz * dz);
} }
float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) { NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta) {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return dx * dx + dy * dy + dz * dz;
}
NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) {
float dx = target.x - current.x; float dx = target.x - current.x;
float dy = target.y - current.y; float dy = target.y - current.y;
float dz = target.z - current.z; float dz = target.z - current.z;
@ -249,29 +55,3 @@ NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target,
float length = std::sqrt(lengthSquared); float length = std::sqrt(lengthSquared);
return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta); return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta);
} }
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) {
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}

View File

@ -1,4 +1,5 @@
#pragma once #ifndef __NIPOINT3_H__
#define __NIPOINT3_H__
/*! /*!
\file NiPoint3.hpp \file NiPoint3.hpp
@ -12,13 +13,13 @@ typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoin
//! A custom class the defines a point in space //! A custom class the defines a point in space
class NiPoint3 { class NiPoint3 {
public: public:
float x; //!< The x position float x{ 0 }; //!< The x position
float y; //!< The y position float y{ 0 }; //!< The y position
float z; //!< The z position float z{ 0 }; //!< The z position
//! Initializer //! Initializer
NiPoint3(void); constexpr NiPoint3() = default;
//! Initializer //! Initializer
/*! /*!
@ -26,23 +27,21 @@ public:
\param y The y coordinate \param y The y coordinate
\param z The z coordinate \param z The z coordinate
*/ */
NiPoint3(float x, float y, float z); constexpr NiPoint3(const float x, const float y, const float z) noexcept
: x{ x }
, y{ y }
, z{ z } {
}
//! Copy Constructor //! Copy Constructor
/*! /*!
\param point The point to copy \param point The point to copy
*/ */
NiPoint3(const NiPoint3& point); constexpr NiPoint3(const NiPoint3& point) noexcept
: x{ point.x }
//! Destructor , y{ point.y }
~NiPoint3(void); , z{ point.z } {
}
// MARK: Constants
static const NiPoint3 ZERO; //!< Point(0, 0, 0)
static const NiPoint3 UNIT_X; //!< Point(1, 0, 0)
static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0)
static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1)
static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1)
// MARK: Getters / Setters // MARK: Getters / Setters
@ -50,38 +49,37 @@ public:
/*! /*!
\return The x coordinate \return The x coordinate
*/ */
float GetX(void) const; [[nodiscard]] constexpr float GetX() const noexcept;
//! Sets the X coordinate //! Sets the X coordinate
/*! /*!
\param x The x coordinate \param x The x coordinate
*/ */
void SetX(float x); constexpr void SetX(const float x) noexcept;
//! Gets the Y coordinate //! Gets the Y coordinate
/*! /*!
\return The y coordinate \return The y coordinate
*/ */
float GetY(void) const; [[nodiscard]] constexpr float GetY() const noexcept;
//! Sets the Y coordinate //! Sets the Y coordinate
/*! /*!
\param y The y coordinate \param y The y coordinate
*/ */
void SetY(float y); constexpr void SetY(const float y) noexcept;
//! Gets the Z coordinate //! Gets the Z coordinate
/*! /*!
\return The z coordinate \return The z coordinate
*/ */
float GetZ(void) const; [[nodiscard]] constexpr float GetZ() const noexcept;
//! Sets the Z coordinate //! Sets the Z coordinate
/*! /*!
\param z The z coordinate \param z The z coordinate
*/ */
void SetZ(float z); constexpr void SetZ(const float z) noexcept;
// MARK: Member Functions // MARK: Member Functions
@ -89,72 +87,70 @@ public:
/*! /*!
\return The scalar length of the vector \return The scalar length of the vector
*/ */
float Length(void) const; [[nodiscard]] float Length() const;
//! Gets the squared length of a vector //! Gets the squared length of a vector
/*! /*!
\return The squared length of a vector \return The squared length of a vector
*/ */
float SquaredLength(void) const; [[nodiscard]] constexpr float SquaredLength() const noexcept;
//! Returns the dot product of the vector dotted with another vector //! Returns the dot product of the vector dotted with another vector
/*! /*!
\param vec The second vector \param vec The second vector
\return The dot product of the two vectors \return The dot product of the two vectors
*/ */
float DotProduct(const Vector3& vec) const; [[nodiscard]] constexpr float DotProduct(const Vector3& vec) const noexcept;
//! Returns the cross product of the vector crossed with another vector //! Returns the cross product of the vector crossed with another vector
/*! /*!
\param vec The second vector \param vec The second vector
\return The cross product of the two vectors \return The cross product of the two vectors
*/ */
Vector3 CrossProduct(const Vector3& vec) const; [[nodiscard]] constexpr Vector3 CrossProduct(const Vector3& vec) const noexcept;
//! Unitize the vector //! Unitize the vector
/*! /*!
\returns The current vector \returns The current vector
*/ */
NiPoint3 Unitize(void) const; [[nodiscard]] NiPoint3 Unitize() const;
// MARK: Operators // MARK: Operators
//! Operator to check for equality //! Operator to check for equality
bool operator==(const NiPoint3& point) const; constexpr bool operator==(const NiPoint3& point) const noexcept;
//! Operator to check for inequality //! Operator to check for inequality
bool operator!=(const NiPoint3& point) const; constexpr bool operator!=(const NiPoint3& point) const noexcept;
//! Operator for subscripting //! Operator for subscripting
float& operator[](int i); constexpr float& operator[](const int i) noexcept;
//! Operator for subscripting //! Operator for subscripting
const float& operator[](int i) const; constexpr const float& operator[](const int i) const noexcept;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 operator+(const NiPoint3& point) const; constexpr NiPoint3 operator+(const NiPoint3& point) const noexcept;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3& operator+=(const NiPoint3& point); constexpr NiPoint3& operator+=(const NiPoint3& point) noexcept;
NiPoint3& operator*=(const float scalar); constexpr NiPoint3& operator*=(const float scalar) noexcept;
//! Operator for subtraction of vectors //! Operator for subtraction of vectors
NiPoint3 operator-(const NiPoint3& point) const; constexpr NiPoint3 operator-(const NiPoint3& point) const noexcept;
//! Operator for addition of a scalar on all vector components //! Operator for addition of a scalar on all vector components
NiPoint3 operator+(float fScalar) const; constexpr NiPoint3 operator+(const float fScalar) const noexcept;
//! Operator for subtraction of a scalar on all vector components //! Operator for subtraction of a scalar on all vector components
NiPoint3 operator-(float fScalar) const; constexpr NiPoint3 operator-(const float fScalar) const noexcept;
//! Operator for scalar multiplication of a vector //! Operator for scalar multiplication of a vector
NiPoint3 operator*(float fScalar) const; constexpr NiPoint3 operator*(const float fScalar) const noexcept;
//! Operator for scalar division of a vector //! Operator for scalar division of a vector
NiPoint3 operator/(float fScalar) const; constexpr NiPoint3 operator/(const float fScalar) const noexcept;
// MARK: Helper Functions // MARK: Helper Functions
@ -164,14 +160,14 @@ public:
\param maxPoint The maximum point of the bounding box \param maxPoint The maximum point of the bounding box
\return Whether or not this point lies within the box \return Whether or not this point lies within the box
*/ */
bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint); [[nodiscard]] constexpr bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept;
//! Checks to see if the point (or vector) is within a sphere //! Checks to see if the point (or vector) is within a sphere
/*! /*!
\param sphereCenter The sphere center \param sphereCenter The sphere center
\param radius The radius \param radius The radius
*/ */
bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius); [[nodiscard]] constexpr bool IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept;
/*! /*!
\param a Start of line \param a Start of line
@ -179,15 +175,30 @@ public:
\param p Refrence point \param p Refrence point
\return The point of line AB which is closest to P \return The point of line AB which is closest to P
*/ */
static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p); [[nodiscard]] static constexpr NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept;
static float Angle(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static float Angle(const NiPoint3& a, const NiPoint3& b);
static float Distance(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static float Distance(const NiPoint3& a, const NiPoint3& b);
static float DistanceSquared(const NiPoint3& a, const NiPoint3& b); [[nodiscard]] static constexpr float DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept;
static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta); [[nodiscard]] static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta);
NiPoint3 RotateByQuaternion(const NiQuaternion& rotation); //This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
[[nodiscard]] constexpr NiPoint3 RotateByQuaternion(const NiQuaternion& rotation) noexcept;
}; };
// Static Variables
namespace NiPoint3Constant {
constexpr NiPoint3 ZERO(0.0f, 0.0f, 0.0f);
constexpr NiPoint3 UNIT_X(1.0f, 0.0f, 0.0f);
constexpr NiPoint3 UNIT_Y(0.0f, 1.0f, 0.0f);
constexpr NiPoint3 UNIT_Z(0.0f, 0.0f, 1.0f);
constexpr NiPoint3 UNIT_ALL(1.0f, 1.0f, 1.0f);
}
// .inl file needed for code organization and to circumvent circular dependency issues
#include "NiPoint3.inl"
#endif // !__NIPOINT3_H__

196
dCommon/NiPoint3.inl Normal file
View File

@ -0,0 +1,196 @@
#pragma once
#ifndef __NIPOINT3_H__
#error "This should only be included inline in NiPoint3.h: Do not include directly!"
#endif
#include "NiQuaternion.h"
// MARK: Getters / Setters
//! Gets the X coordinate
constexpr float NiPoint3::GetX() const noexcept {
return this->x;
}
//! Sets the X coordinate
constexpr void NiPoint3::SetX(const float x) noexcept {
this->x = x;
}
//! Gets the Y coordinate
constexpr float NiPoint3::GetY() const noexcept {
return this->y;
}
//! Sets the Y coordinate
constexpr void NiPoint3::SetY(const float y) noexcept {
this->y = y;
}
//! Gets the Z coordinate
constexpr float NiPoint3::GetZ() const noexcept {
return this->z;
}
//! Sets the Z coordinate
constexpr void NiPoint3::SetZ(const float z) noexcept {
this->z = z;
}
// MARK: Member Functions
//! Gets the squared length of a vector
constexpr float NiPoint3::SquaredLength() const noexcept {
return (x * x + y * y + z * z);
}
//! Returns the dot product of the vector dotted with another vector
constexpr float NiPoint3::DotProduct(const Vector3& vec) const noexcept {
return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z));
}
//! Returns the cross product of the vector crossed with another vector
constexpr Vector3 NiPoint3::CrossProduct(const Vector3& vec) const noexcept {
return Vector3(((this->y * vec.z) - (this->z * vec.y)),
((this->z * vec.x) - (this->x * vec.z)),
((this->x * vec.y) - (this->y * vec.x)));
}
// MARK: Operators
//! Operator to check for equality
constexpr bool NiPoint3::operator==(const NiPoint3& point) const noexcept {
return point.x == this->x && point.y == this->y && point.z == this->z;
}
//! Operator to check for inequality
constexpr bool NiPoint3::operator!=(const NiPoint3& point) const noexcept {
return !(*this == point);
}
//! Operator for subscripting
constexpr float& NiPoint3::operator[](const int i) noexcept {
float* base = &x;
return base[i];
}
//! Operator for subscripting
constexpr const float& NiPoint3::operator[](const int i) const noexcept {
const float* base = &x;
return base[i];
}
//! Operator for addition of vectors
constexpr NiPoint3 NiPoint3::operator+(const NiPoint3& point) const noexcept {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
}
//! Operator for addition of vectors
constexpr NiPoint3& NiPoint3::operator+=(const NiPoint3& point) noexcept {
this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
}
constexpr NiPoint3& NiPoint3::operator*=(const float scalar) noexcept {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors
constexpr NiPoint3 NiPoint3::operator-(const NiPoint3& point) const noexcept {
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
}
//! Operator for addition of a scalar on all vector components
constexpr NiPoint3 NiPoint3::operator+(const float fScalar) const noexcept {
return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar);
}
//! Operator for subtraction of a scalar on all vector components
constexpr NiPoint3 NiPoint3::operator-(const float fScalar) const noexcept {
return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar);
}
//! Operator for scalar multiplication of a vector
constexpr NiPoint3 NiPoint3::operator*(const float fScalar) const noexcept {
return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar);
}
//! Operator for scalar division of a vector
constexpr NiPoint3 NiPoint3::operator/(const float fScalar) const noexcept {
float retX = this->x != 0 ? this->x / fScalar : 0;
float retY = this->y != 0 ? this->y / fScalar : 0;
float retZ = this->z != 0 ? this->z / fScalar : 0;
return NiPoint3(retX, retY, retZ);
}
// MARK: Helper Functions
//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box
constexpr bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept {
if (this->x < minPoint.x) return false;
if (this->x > maxPoint.x) return false;
if (this->y < minPoint.y) return false;
if (this->y > maxPoint.y) return false;
return (this->z < maxPoint.z && this->z > minPoint.z);
}
//! Checks to see if the point (or vector) is within a sphere
constexpr bool NiPoint3::IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept {
Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ());
return (diffVec.SquaredLength() <= (radius * radius));
}
constexpr NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept {
if (a == b) return a;
const auto pa = p - a;
const auto ab = b - a;
const auto t = pa.DotProduct(ab) / ab.SquaredLength();
if (t <= 0.0f) return a;
if (t >= 1.0f) return b;
return a + ab * t;
}
constexpr float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept {
const auto dx = a.x - b.x;
const auto dy = a.y - b.y;
const auto dz = a.z - b.z;
return dx * dx + dy * dy + dz * dz;
}
//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible.
constexpr NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) noexcept {
Vector3 vector;
float num12 = rotation.x + rotation.x;
float num2 = rotation.y + rotation.y;
float num = rotation.z + rotation.z;
float num11 = rotation.w * num12;
float num10 = rotation.w * num2;
float num9 = rotation.w * num;
float num8 = rotation.x * num12;
float num7 = rotation.x * num2;
float num6 = rotation.x * num;
float num5 = rotation.y * num2;
float num4 = rotation.y * num;
float num3 = rotation.z * num;
NiPoint3 value = *this;
float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10));
float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11));
float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5));
vector.x = num15;
vector.y = num14;
vector.z = num13;
return vector;
}

View File

@ -3,89 +3,8 @@
// C++ // C++
#include <cmath> #include <cmath>
// Static Variables
const NiQuaternion NiQuaternion::IDENTITY(1, 0, 0, 0);
//! The initializer
NiQuaternion::NiQuaternion(void) {
this->w = 1;
this->x = 0;
this->y = 0;
this->z = 0;
}
//! The initializer
NiQuaternion::NiQuaternion(float w, float x, float y, float z) {
this->w = w;
this->x = x;
this->y = y;
this->z = z;
}
//! Destructor
NiQuaternion::~NiQuaternion(void) {}
// MARK: Setters / Getters
//! Gets the W coordinate
float NiQuaternion::GetW(void) const {
return this->w;
}
//! Sets the W coordinate
void NiQuaternion::SetW(float w) {
this->w = w;
}
//! Gets the X coordinate
float NiQuaternion::GetX(void) const {
return this->x;
}
//! Sets the X coordinate
void NiQuaternion::SetX(float x) {
this->x = x;
}
//! Gets the Y coordinate
float NiQuaternion::GetY(void) const {
return this->y;
}
//! Sets the Y coordinate
void NiQuaternion::SetY(float y) {
this->y = y;
}
//! Gets the Z coordinate
float NiQuaternion::GetZ(void) const {
return this->z;
}
//! Sets the Z coordinate
void NiQuaternion::SetZ(float z) {
this->z = z;
}
// MARK: Member Functions // MARK: Member Functions
//! Returns the forward vector from the quaternion
Vector3 NiQuaternion::GetForwardVector(void) const {
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
//! Returns the up vector from the quaternion
Vector3 NiQuaternion::GetUpVector(void) const {
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
//! Returns the right vector from the quaternion
Vector3 NiQuaternion::GetRightVector(void) const {
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
Vector3 NiQuaternion::GetEulerAngles() const { Vector3 NiQuaternion::GetEulerAngles() const {
Vector3 angles; Vector3 angles;
@ -111,22 +30,9 @@ Vector3 NiQuaternion::GetEulerAngles() const {
return angles; return angles;
} }
// MARK: Operators
//! Operator to check for equality
bool NiQuaternion::operator==(const NiQuaternion& rot) const {
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
}
//! Operator to check for inequality
bool NiQuaternion::operator!=(const NiQuaternion& rot) const {
return !(*this == rot);
}
// MARK: Helper Functions // MARK: Helper Functions
//! Look from a specific point in space to another point in space //! Look from a specific point in space to another point in space (Y-locked)
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
//To make sure we don't orient around the X/Z axis: //To make sure we don't orient around the X/Z axis:
NiPoint3 source = sourcePoint; NiPoint3 source = sourcePoint;
@ -136,7 +42,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
NiPoint3 forwardVector = NiPoint3(dest - source).Unitize(); NiPoint3 forwardVector = NiPoint3(dest - source).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z; NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector); float dot = posZ.DotProduct(forwardVector);
@ -148,10 +54,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle); return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
} }
//! Look from a specific point in space to another point in space
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize(); NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
NiPoint3 posZ = NiPoint3::UNIT_Z; NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize();
float dot = posZ.DotProduct(forwardVector); float dot = posZ.DotProduct(forwardVector);

View File

@ -1,4 +1,5 @@
#pragma once #ifndef __NIQUATERNION_H__
#define __NIQUATERNION_H__
// Custom Classes // Custom Classes
#include "NiPoint3.h" #include "NiPoint3.h"
@ -14,14 +15,14 @@ typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version o
//! A class that defines a rotation in space //! A class that defines a rotation in space
class NiQuaternion { class NiQuaternion {
public: public:
float w; //!< The w coordinate float w{ 1 }; //!< The w coordinate
float x; //!< The x coordinate float x{ 0 }; //!< The x coordinate
float y; //!< The y coordinate float y{ 0 }; //!< The y coordinate
float z; //!< The z coordinate float z{ 0 }; //!< The z coordinate
//! The initializer //! The initializer
NiQuaternion(void); constexpr NiQuaternion() = default;
//! The initializer //! The initializer
/*! /*!
@ -30,13 +31,12 @@ public:
\param y The y coordinate \param y The y coordinate
\param z The z coordinate \param z The z coordinate
*/ */
NiQuaternion(float w, float x, float y, float z); constexpr NiQuaternion(const float w, const float x, const float y, const float z) noexcept
: w{ w }
//! Destructor , x{ x }
~NiQuaternion(void); , y{ y }
, z{ z } {
// MARK: Constants }
static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0)
// MARK: Setters / Getters // MARK: Setters / Getters
@ -44,50 +44,49 @@ public:
/*! /*!
\return The w coordinate \return The w coordinate
*/ */
float GetW(void) const; [[nodiscard]] constexpr float GetW() const noexcept;
//! Sets the W coordinate //! Sets the W coordinate
/*! /*!
\param w The w coordinate \param w The w coordinate
*/ */
void SetW(float w); constexpr void SetW(const float w) noexcept;
//! Gets the X coordinate //! Gets the X coordinate
/*! /*!
\return The x coordinate \return The x coordinate
*/ */
float GetX(void) const; [[nodiscard]] constexpr float GetX() const noexcept;
//! Sets the X coordinate //! Sets the X coordinate
/*! /*!
\param x The x coordinate \param x The x coordinate
*/ */
void SetX(float x); constexpr void SetX(const float x) noexcept;
//! Gets the Y coordinate //! Gets the Y coordinate
/*! /*!
\return The y coordinate \return The y coordinate
*/ */
float GetY(void) const; [[nodiscard]] constexpr float GetY() const noexcept;
//! Sets the Y coordinate //! Sets the Y coordinate
/*! /*!
\param y The y coordinate \param y The y coordinate
*/ */
void SetY(float y); constexpr void SetY(const float y) noexcept;
//! Gets the Z coordinate //! Gets the Z coordinate
/*! /*!
\return The z coordinate \return The z coordinate
*/ */
float GetZ(void) const; [[nodiscard]] constexpr float GetZ() const noexcept;
//! Sets the Z coordinate //! Sets the Z coordinate
/*! /*!
\param z The z coordinate \param z The z coordinate
*/ */
void SetZ(float z); constexpr void SetZ(const float z) noexcept;
// MARK: Member Functions // MARK: Member Functions
@ -95,31 +94,29 @@ public:
/*! /*!
\return The forward vector of the quaternion \return The forward vector of the quaternion
*/ */
Vector3 GetForwardVector(void) const; [[nodiscard]] constexpr Vector3 GetForwardVector() const noexcept;
//! Returns the up vector from the quaternion //! Returns the up vector from the quaternion
/*! /*!
\return The up vector fo the quaternion \return The up vector fo the quaternion
*/ */
Vector3 GetUpVector(void) const; [[nodiscard]] constexpr Vector3 GetUpVector() const noexcept;
//! Returns the right vector from the quaternion //! Returns the right vector from the quaternion
/*! /*!
\return The right vector of the quaternion \return The right vector of the quaternion
*/ */
Vector3 GetRightVector(void) const; [[nodiscard]] constexpr Vector3 GetRightVector() const noexcept;
Vector3 GetEulerAngles() const;
[[nodiscard]] Vector3 GetEulerAngles() const;
// MARK: Operators // MARK: Operators
//! Operator to check for equality //! Operator to check for equality
bool operator==(const NiQuaternion& rot) const; constexpr bool operator==(const NiQuaternion& rot) const noexcept;
//! Operator to check for inequality //! Operator to check for inequality
bool operator!=(const NiQuaternion& rot) const; constexpr bool operator!=(const NiQuaternion& rot) const noexcept;
// MARK: Helper Functions // MARK: Helper Functions
@ -129,7 +126,7 @@ public:
\param destPoint The destination location \param destPoint The destination location
\return The Quaternion with the rotation towards the destination \return The Quaternion with the rotation towards the destination
*/ */
static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint); [[nodiscard]] static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Look from a specific point in space to another point in space //! Look from a specific point in space to another point in space
/*! /*!
@ -137,7 +134,7 @@ public:
\param destPoint The destination location \param destPoint The destination location
\return The Quaternion with the rotation towards the destination \return The Quaternion with the rotation towards the destination
*/ */
static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint); [[nodiscard]] static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
//! Creates a Quaternion from a specific axis and angle relative to that axis //! Creates a Quaternion from a specific axis and angle relative to that axis
/*! /*!
@ -145,7 +142,17 @@ public:
\param angle The angle relative to this axis \param angle The angle relative to this axis
\return A quaternion created from the axis and angle \return A quaternion created from the axis and angle
*/ */
static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle); [[nodiscard]] static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles); [[nodiscard]] static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
}; };
// Static Variables
namespace NiQuaternionConstant {
constexpr NiQuaternion IDENTITY(1, 0, 0, 0);
}
// Include constexpr and inline function definitions in a seperate file for readability
#include "NiQuaternion.inl"
#endif // !__NIQUATERNION_H__

75
dCommon/NiQuaternion.inl Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#ifndef __NIQUATERNION_H__
#error "This should only be included inline in NiQuaternion.h: Do not include directly!"
#endif
// MARK: Setters / Getters
//! Gets the W coordinate
constexpr float NiQuaternion::GetW() const noexcept {
return this->w;
}
//! Sets the W coordinate
constexpr void NiQuaternion::SetW(const float w) noexcept {
this->w = w;
}
//! Gets the X coordinate
constexpr float NiQuaternion::GetX() const noexcept {
return this->x;
}
//! Sets the X coordinate
constexpr void NiQuaternion::SetX(const float x) noexcept {
this->x = x;
}
//! Gets the Y coordinate
constexpr float NiQuaternion::GetY() const noexcept {
return this->y;
}
//! Sets the Y coordinate
constexpr void NiQuaternion::SetY(const float y) noexcept {
this->y = y;
}
//! Gets the Z coordinate
constexpr float NiQuaternion::GetZ() const noexcept {
return this->z;
}
//! Sets the Z coordinate
constexpr void NiQuaternion::SetZ(const float z) noexcept {
this->z = z;
}
// MARK: Member Functions
//! Returns the forward vector from the quaternion
constexpr Vector3 NiQuaternion::GetForwardVector() const noexcept {
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
}
//! Returns the up vector from the quaternion
constexpr Vector3 NiQuaternion::GetUpVector() const noexcept {
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
}
//! Returns the right vector from the quaternion
constexpr Vector3 NiQuaternion::GetRightVector() const noexcept {
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
}
// MARK: Operators
//! Operator to check for equality
constexpr bool NiQuaternion::operator==(const NiQuaternion& rot) const noexcept {
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
}
//! Operator to check for inequality
constexpr bool NiQuaternion::operator!=(const NiQuaternion& rot) const noexcept {
return !(*this == rot);
}

View File

@ -32,17 +32,17 @@ struct RemoteInputInfo {
struct LocalSpaceInfo { struct LocalSpaceInfo {
LWOOBJID objectId = LWOOBJID_EMPTY; LWOOBJID objectId = LWOOBJID_EMPTY;
NiPoint3 position = NiPoint3::ZERO; NiPoint3 position = NiPoint3Constant::ZERO;
NiPoint3 linearVelocity = NiPoint3::ZERO; NiPoint3 linearVelocity = NiPoint3Constant::ZERO;
}; };
struct PositionUpdate { struct PositionUpdate {
NiPoint3 position = NiPoint3::ZERO; NiPoint3 position = NiPoint3Constant::ZERO;
NiQuaternion rotation = NiQuaternion::IDENTITY; NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
bool onGround = false; bool onGround = false;
bool onRail = false; bool onRail = false;
NiPoint3 velocity = NiPoint3::ZERO; NiPoint3 velocity = NiPoint3Constant::ZERO;
NiPoint3 angularVelocity = NiPoint3::ZERO; NiPoint3 angularVelocity = NiPoint3Constant::ZERO;
LocalSpaceInfo localSpaceInfo; LocalSpaceInfo localSpaceInfo;
RemoteInputInfo remoteInputInfo; RemoteInputInfo remoteInputInfo;
}; };

View File

@ -1,154 +0,0 @@
// Source: http://www.zedwood.com/article/cpp-sha512-function
#include "SHA512.h"
#include <cstring>
#include <fstream>
const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
{ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL };
void SHA512::transform(const unsigned char* message, unsigned int block_nb) {
uint64 w[80];
uint64 wv[8];
uint64 t1, t2;
const unsigned char* sub_block;
int i, j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 7);
for (j = 0; j < 16; j++) {
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++) {
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++) {
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha512_k[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
}
void SHA512::init() {
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
}
void SHA512::update(const unsigned char* message, unsigned int len) {
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char* shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
}
void SHA512::final(unsigned char* digest) {
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
}
std::string sha512(std::string input) {
unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest, 0, SHA512::DIGEST_SIZE);
class SHA512 ctx;
ctx.init();
ctx.update((unsigned char*)input.c_str(), input.length());
ctx.final(digest);
char buf[2 * SHA512::DIGEST_SIZE + 1];
buf[2 * SHA512::DIGEST_SIZE] = 0;
for (int i = 0; i < SHA512::DIGEST_SIZE; i++)
sprintf(buf + i * 2, "%02x", digest[i]);
return std::string(buf);
}

View File

@ -1,68 +0,0 @@
#pragma once
// C++
#include <string>
class SHA512 {
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint64 sha512_k[];
static const unsigned int SHA384_512_BLOCK_SIZE = (1024 / 8);
public:
void init();
void update(const unsigned char* message, unsigned int len);
void final(unsigned char* digest);
static const unsigned int DIGEST_SIZE = (512 / 8);
protected:
void transform(const unsigned char* message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
};
std::string sha512(std::string input);
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA512_F1(x) (SHA2_ROTR(x, 28) ^ SHA2_ROTR(x, 34) ^ SHA2_ROTR(x, 39))
#define SHA512_F2(x) (SHA2_ROTR(x, 14) ^ SHA2_ROTR(x, 18) ^ SHA2_ROTR(x, 41))
#define SHA512_F3(x) (SHA2_ROTR(x, 1) ^ SHA2_ROTR(x, 8) ^ SHA2_SHFR(x, 7))
#define SHA512_F4(x) (SHA2_ROTR(x, 19) ^ SHA2_ROTR(x, 61) ^ SHA2_SHFR(x, 6))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_UNPACK64(x, str) \
{ \
*((str) + 7) = (uint8) ((x) ); \
*((str) + 6) = (uint8) ((x) >> 8); \
*((str) + 5) = (uint8) ((x) >> 16); \
*((str) + 4) = (uint8) ((x) >> 24); \
*((str) + 3) = (uint8) ((x) >> 32); \
*((str) + 2) = (uint8) ((x) >> 40); \
*((str) + 1) = (uint8) ((x) >> 48); \
*((str) + 0) = (uint8) ((x) >> 56); \
}
#define SHA2_PACK64(str, x) \
{ \
*(x) = ((uint64) *((str) + 7) ) \
| ((uint64) *((str) + 6) << 8) \
| ((uint64) *((str) + 5) << 16) \
| ((uint64) *((str) + 4) << 24) \
| ((uint64) *((str) + 3) << 32) \
| ((uint64) *((str) + 2) << 40) \
| ((uint64) *((str) + 1) << 48) \
| ((uint64) *((str) + 0) << 56); \
}

View File

@ -1,6 +1,6 @@
set(DCOMMON_DCLIENT_SOURCES set(DCOMMON_DCLIENT_SOURCES
"AssetManager.cpp"
"PackIndex.cpp" "PackIndex.cpp"
"Pack.cpp" "Pack.cpp"
"AssetManager.cpp"
PARENT_SCOPE PARENT_SCOPE
) )

View File

@ -0,0 +1,12 @@
#ifndef __CLIENTVERSION_H__
#define __CLIENTVERSION_H__
#include <cstdint>
namespace ClientVersion {
constexpr uint16_t major = 1;
constexpr uint16_t current = 10;
constexpr uint16_t minor = 64;
}
#endif // !__CLIENTVERSION_H__

View File

@ -39,86 +39,84 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
//=========== TYPEDEFS ========== //=========== TYPEDEFS ==========
typedef int32_t LOT; //!< A LOT using LOT = int32_t; //!< A LOT
typedef int64_t LWOOBJID; //!< An object ID (should be unsigned actually but ok) using LWOOBJID = int64_t; //!< An object ID (should be unsigned actually but ok)
typedef int32_t TSkillID; //!< A skill ID using TSkillID = int32_t; //!< A skill ID
typedef uint32_t LWOCLONEID; //!< Used for Clone IDs using LWOCLONEID = uint32_t; //!< Used for Clone IDs
typedef uint16_t LWOMAPID; //!< Used for Map IDs using LWOMAPID = uint16_t; //!< Used for Map IDs
typedef uint16_t LWOINSTANCEID; //!< Used for Instance IDs using LWOINSTANCEID = uint16_t; //!< Used for Instance IDs
typedef uint32_t PROPERTYCLONELIST; //!< Used for Property Clone IDs using PROPERTYCLONELIST = uint32_t; //!< Used for Property Clone IDs
typedef uint32_t StripId; using StripId = uint32_t;
const LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID constexpr LWOOBJID LWOOBJID_EMPTY = 0; //!< An empty object ID
const LOT LOT_NULL = -1; //!< A null LOT constexpr LOT LOT_NULL = -1; //!< A null LOT
const int32_t LOOTTYPE_NONE = 0; //!< No loot type available constexpr int32_t LOOTTYPE_NONE = 0; //!< No loot type available
const float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority constexpr float SECONDARY_PRIORITY = 1.0f; //!< Secondary Priority
const uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size constexpr uint32_t INVENTORY_MAX = 9999999; //!< The Maximum Inventory Size
const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID constexpr LWOCLONEID LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID constexpr LWOINSTANCEID LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID constexpr LWOMAPID LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID constexpr uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID
const float PI = 3.14159f; constexpr float PI = 3.14159f;
//============ STRUCTS ============== //============ STRUCTS ==============
struct LWOSCENEID { struct LWOSCENEID {
public: public:
LWOSCENEID() { m_sceneID = -1; m_layerID = 0; } constexpr LWOSCENEID() noexcept { m_sceneID = -1; m_layerID = 0; }
LWOSCENEID(int sceneID) { m_sceneID = sceneID; m_layerID = 0; } constexpr LWOSCENEID(int32_t sceneID) noexcept { m_sceneID = sceneID; m_layerID = 0; }
LWOSCENEID(int sceneID, unsigned int layerID) { m_sceneID = sceneID; m_layerID = layerID; } constexpr LWOSCENEID(int32_t sceneID, uint32_t layerID) noexcept { m_sceneID = sceneID; m_layerID = layerID; }
LWOSCENEID& operator=(const LWOSCENEID& rhs) { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; } constexpr LWOSCENEID& operator=(const LWOSCENEID& rhs) noexcept { m_sceneID = rhs.m_sceneID; m_layerID = rhs.m_layerID; return *this; }
LWOSCENEID& operator=(const int rhs) { m_sceneID = rhs; m_layerID = 0; return *this; } constexpr LWOSCENEID& operator=(const int32_t rhs) noexcept { m_sceneID = rhs; m_layerID = 0; return *this; }
bool operator<(const LWOSCENEID& rhs) const { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); } constexpr bool operator<(const LWOSCENEID& rhs) const noexcept { return (m_sceneID < rhs.m_sceneID || (m_sceneID == rhs.m_sceneID && m_layerID < rhs.m_layerID)); }
bool operator<(const int rhs) const { return m_sceneID < rhs; } constexpr bool operator<(const int32_t rhs) const noexcept { return m_sceneID < rhs; }
bool operator==(const LWOSCENEID& rhs) const { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); } constexpr bool operator==(const LWOSCENEID& rhs) const noexcept { return (m_sceneID == rhs.m_sceneID && m_layerID == rhs.m_layerID); }
bool operator==(const int rhs) const { return m_sceneID == rhs; } constexpr bool operator==(const int32_t rhs) const noexcept { return m_sceneID == rhs; }
const int GetSceneID() const { return m_sceneID; } constexpr int32_t GetSceneID() const noexcept { return m_sceneID; }
const unsigned int GetLayerID() const { return m_layerID; } constexpr uint32_t GetLayerID() const noexcept { return m_layerID; }
void SetSceneID(const int sceneID) { m_sceneID = sceneID; } constexpr void SetSceneID(const int32_t sceneID) noexcept { m_sceneID = sceneID; }
void SetLayerID(const unsigned int layerID) { m_layerID = layerID; } constexpr void SetLayerID(const uint32_t layerID) noexcept { m_layerID = layerID; }
private: private:
int m_sceneID; int32_t m_sceneID;
unsigned int m_layerID; uint32_t m_layerID;
}; };
struct LWOZONEID { struct LWOZONEID {
public: public:
const LWOMAPID& GetMapID() const { return m_MapID; } constexpr const LWOMAPID& GetMapID() const noexcept { return m_MapID; }
const LWOINSTANCEID& GetInstanceID() const { return m_InstanceID; } constexpr const LWOINSTANCEID& GetInstanceID() const noexcept { return m_InstanceID; }
const LWOCLONEID& GetCloneID() const { return m_CloneID; } constexpr const LWOCLONEID& GetCloneID() const noexcept { return m_CloneID; }
//In order: def constr, constr, assign op //In order: def constr, constr, assign op
LWOZONEID() { m_MapID = LWOMAPID_INVALID; m_InstanceID = LWOINSTANCEID_INVALID; m_CloneID = LWOCLONEID_INVALID; } constexpr LWOZONEID() noexcept = default;
LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; } constexpr LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) noexcept { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
LWOZONEID(const LWOZONEID& replacement) { *this = replacement; } constexpr LWOZONEID(const LWOZONEID& replacement) noexcept { *this = replacement; }
private: private:
LWOMAPID m_MapID; //1000 for VE, 1100 for AG, etc... LWOMAPID m_MapID = LWOMAPID_INVALID; //1000 for VE, 1100 for AG, etc...
LWOINSTANCEID m_InstanceID; //Instances host the same world, but on a different dWorld process. LWOINSTANCEID m_InstanceID = LWOINSTANCEID_INVALID; //Instances host the same world, but on a different dWorld process.
LWOCLONEID m_CloneID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds. LWOCLONEID m_CloneID = LWOCLONEID_INVALID; //To differentiate between "your property" and "my property". Always 0 for non-prop worlds.
}; };
const LWOSCENEID LWOSCENEID_INVALID = -1; constexpr LWOSCENEID LWOSCENEID_INVALID = -1;
struct LWONameValue { struct LWONameValue {
uint32_t length = 0; //!< The length of the name uint32_t length = 0; //!< The length of the name
std::u16string name; //!< The name std::u16string name; //!< The name
LWONameValue(void) {} LWONameValue() = default;
LWONameValue(const std::u16string& name) { LWONameValue(const std::u16string& name) {
this->name = name; this->name = name;
this->length = static_cast<uint32_t>(name.length()); this->length = static_cast<uint32_t>(name.length());
} }
~LWONameValue(void) {}
}; };
struct FriendData { struct FriendData {

View File

@ -39,6 +39,7 @@
#include "CDFeatureGatingTable.h" #include "CDFeatureGatingTable.h"
#include "CDRailActivatorComponent.h" #include "CDRailActivatorComponent.h"
#include "CDRewardCodesTable.h" #include "CDRewardCodesTable.h"
#include "CDPetComponentTable.h"
#include <exception> #include <exception>
@ -61,6 +62,55 @@ public:
} }
}; };
// Using a macro to reduce repetitive code and issues from copy and paste.
// As a note, ## in a macro is used to concatenate two tokens together.
#define SPECIALIZE_TABLE_STORAGE(table) \
template<> typename table::StorageType& CDClientManager::GetEntriesMutable<table>() { return table##Entries; };
#define DEFINE_TABLE_STORAGE(table) namespace { table::StorageType table##Entries; }; SPECIALIZE_TABLE_STORAGE(table)
DEFINE_TABLE_STORAGE(CDActivityRewardsTable);
DEFINE_TABLE_STORAGE(CDActivitiesTable);
DEFINE_TABLE_STORAGE(CDAnimationsTable);
DEFINE_TABLE_STORAGE(CDBehaviorParameterTable);
DEFINE_TABLE_STORAGE(CDBehaviorTemplateTable);
DEFINE_TABLE_STORAGE(CDBrickIDTableTable);
DEFINE_TABLE_STORAGE(CDComponentsRegistryTable);
DEFINE_TABLE_STORAGE(CDCurrencyTableTable);
DEFINE_TABLE_STORAGE(CDDestructibleComponentTable);
DEFINE_TABLE_STORAGE(CDEmoteTableTable);
DEFINE_TABLE_STORAGE(CDFeatureGatingTable);
DEFINE_TABLE_STORAGE(CDInventoryComponentTable);
DEFINE_TABLE_STORAGE(CDItemComponentTable);
DEFINE_TABLE_STORAGE(CDItemSetSkillsTable);
DEFINE_TABLE_STORAGE(CDItemSetsTable);
DEFINE_TABLE_STORAGE(CDLevelProgressionLookupTable);
DEFINE_TABLE_STORAGE(CDLootMatrixTable);
DEFINE_TABLE_STORAGE(CDLootTableTable);
DEFINE_TABLE_STORAGE(CDMissionEmailTable);
DEFINE_TABLE_STORAGE(CDMissionNPCComponentTable);
DEFINE_TABLE_STORAGE(CDMissionTasksTable);
DEFINE_TABLE_STORAGE(CDMissionsTable);
DEFINE_TABLE_STORAGE(CDMovementAIComponentTable);
DEFINE_TABLE_STORAGE(CDObjectSkillsTable);
DEFINE_TABLE_STORAGE(CDObjectsTable);
DEFINE_TABLE_STORAGE(CDPhysicsComponentTable);
DEFINE_TABLE_STORAGE(CDPackageComponentTable);
DEFINE_TABLE_STORAGE(CDPetComponentTable);
DEFINE_TABLE_STORAGE(CDProximityMonitorComponentTable);
DEFINE_TABLE_STORAGE(CDPropertyEntranceComponentTable);
DEFINE_TABLE_STORAGE(CDPropertyTemplateTable);
DEFINE_TABLE_STORAGE(CDRailActivatorComponentTable);
DEFINE_TABLE_STORAGE(CDRarityTableTable);
DEFINE_TABLE_STORAGE(CDRebuildComponentTable);
DEFINE_TABLE_STORAGE(CDRewardCodesTable);
DEFINE_TABLE_STORAGE(CDRewardsTable);
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
DEFINE_TABLE_STORAGE(CDZoneTableTable);
void CDClientManager::LoadValuesFromDatabase() { void CDClientManager::LoadValuesFromDatabase() {
if (!CDClientDatabase::isConnected) throw CDClientConnectionException(); if (!CDClientDatabase::isConnected) throw CDClientConnectionException();

View File

@ -1,18 +1,12 @@
#pragma once #ifndef __CDCLIENTMANAGER__H__
#define __CDCLIENTMANAGER__H__
#include "CDTable.h"
#include "Singleton.h"
#define UNUSED_TABLE(v) #define UNUSED_TABLE(v)
/** /**
* Initialize the CDClient tables so they are all loaded into memory. * Initialize the CDClient tables so they are all loaded into memory.
*/ */
class CDClientManager : public Singleton<CDClientManager> { namespace CDClientManager {
public:
CDClientManager() = default;
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
void LoadValuesFromDefaults(); void LoadValuesFromDefaults();
@ -23,7 +17,28 @@ public:
* @return A pointer to the requested table. * @return A pointer to the requested table.
*/ */
template<typename T> template<typename T>
T* GetTable() { T* GetTable();
return &T::Instance();
} /**
* Fetch a table from CDClient
* Note: Calling this function without a template specialization in CDClientManager.cpp will cause a linker error.
*
* @tparam Table type to fetch
* @return A pointer to the requested table.
*/
template<typename T>
typename T::StorageType& GetEntriesMutable();
}; };
// These are included after the CDClientManager namespace declaration as CDTable as of Jan 29 2024 relies on CDClientManager in Templated code.
#include "CDTable.h"
#include "Singleton.h"
template<typename T>
T* CDClientManager::GetTable() {
return &T::Instance();
};
#endif //!__CDCLIENTMANAGER__H__

View File

@ -1,5 +1,6 @@
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
void CDActivitiesTable::LoadValuesFromDatabase() { void CDActivitiesTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
@ -13,7 +14,8 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Activities"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Activities");
@ -39,7 +41,7 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
entry.noTeamLootOnDeath = tableData.getIntField("noTeamLootOnDeath", -1); entry.noTeamLootOnDeath = tableData.getIntField("noTeamLootOnDeath", -1);
entry.optionalPercentage = tableData.getFloatField("optionalPercentage", -1.0f); entry.optionalPercentage = tableData.getFloatField("optionalPercentage", -1.0f);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -48,7 +50,7 @@ void CDActivitiesTable::LoadValuesFromDatabase() {
std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActivities)> predicate) { std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActivities)> predicate) {
std::vector<CDActivities> data = cpplinq::from(this->entries) std::vector<CDActivities> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();

View File

@ -25,15 +25,10 @@ struct CDActivities {
float optionalPercentage; float optionalPercentage;
}; };
class CDActivitiesTable : public CDTable<CDActivitiesTable> { class CDActivitiesTable : public CDTable<CDActivitiesTable, std::vector<CDActivities>> {
private:
std::vector<CDActivities> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate); std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
const std::vector<CDActivities>& GetEntries() const { return this->entries; }
}; };

View File

@ -1,5 +1,6 @@
#include "CDActivityRewardsTable.h" #include "CDActivityRewardsTable.h"
void CDActivityRewardsTable::LoadValuesFromDatabase() { void CDActivityRewardsTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -14,7 +15,8 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ActivityRewards"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ActivityRewards");
@ -28,7 +30,7 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
entry.ChallengeRating = tableData.getIntField("ChallengeRating", -1); entry.ChallengeRating = tableData.getIntField("ChallengeRating", -1);
entry.description = tableData.getStringField("description", ""); entry.description = tableData.getStringField("description", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -37,7 +39,7 @@ void CDActivityRewardsTable::LoadValuesFromDatabase() {
std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(CDActivityRewards)> predicate) { std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(CDActivityRewards)> predicate) {
std::vector<CDActivityRewards> data = cpplinq::from(this->entries) std::vector<CDActivityRewards> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();

View File

@ -13,15 +13,9 @@ struct CDActivityRewards {
std::string description; //!< The description std::string description; //!< The description
}; };
class CDActivityRewardsTable : public CDTable<CDActivityRewardsTable> { class CDActivityRewardsTable : public CDTable<CDActivityRewardsTable, std::vector<CDActivityRewards>> {
private:
std::vector<CDActivityRewards> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate); std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
std::vector<CDActivityRewards> GetEntries() const;
}; };

View File

@ -5,6 +5,7 @@
void CDAnimationsTable::LoadValuesFromDatabase() { void CDAnimationsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
auto& animations = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
std::string animation_type = tableData.getStringField("animation_type", ""); std::string animation_type = tableData.getStringField("animation_type", "");
DluAssert(!animation_type.empty()); DluAssert(!animation_type.empty());
@ -24,7 +25,7 @@ void CDAnimationsTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);) UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);) UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry); animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,6 +36,7 @@ bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
auto tableData = queryToCache.execQuery(); auto tableData = queryToCache.execQuery();
// If we received a bad lookup, cache it anyways so we do not run the query again. // If we received a bad lookup, cache it anyways so we do not run the query again.
if (tableData.eof()) return false; if (tableData.eof()) return false;
auto& animations = GetEntriesMutable();
do { do {
std::string animation_type = tableData.getStringField("animation_type", ""); std::string animation_type = tableData.getStringField("animation_type", "");
@ -55,7 +57,7 @@ bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);) UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);) UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry); animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
tableData.nextRow(); tableData.nextRow();
} while (!tableData.eof()); } while (!tableData.eof());
@ -68,15 +70,17 @@ void CDAnimationsTable::CacheAnimations(const CDAnimationKey animationKey) {
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?"); auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?");
query.bind(1, static_cast<int32_t>(animationKey.second)); query.bind(1, static_cast<int32_t>(animationKey.second));
query.bind(2, animationKey.first.c_str()); query.bind(2, animationKey.first.c_str());
auto& animations = GetEntriesMutable();
// If we received a bad lookup, cache it anyways so we do not run the query again. // If we received a bad lookup, cache it anyways so we do not run the query again.
if (!CacheData(query)) { if (!CacheData(query)) {
this->animations[animationKey]; animations[animationKey];
} }
} }
void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) { void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
auto animationEntryCached = this->animations.find(CDAnimationKey("", animationGroupID)); auto& animations = GetEntriesMutable();
if (animationEntryCached != this->animations.end()) { auto animationEntryCached = animations.find(CDAnimationKey("", animationGroupID));
if (animationEntryCached != animations.end()) {
return; return;
} }
@ -85,28 +89,29 @@ void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
// Cache the query so we don't run the query again. // Cache the query so we don't run the query again.
CacheData(query); CacheData(query);
this->animations[CDAnimationKey("", animationGroupID)]; animations[CDAnimationKey("", animationGroupID)];
} }
CDAnimationLookupResult CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) { std::optional<CDAnimation> CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) {
auto& animations = GetEntriesMutable();
CDAnimationKey animationKey(animationType, animationGroupID); CDAnimationKey animationKey(animationType, animationGroupID);
auto animationEntryCached = this->animations.find(animationKey); auto animationEntryCached = animations.find(animationKey);
if (animationEntryCached == this->animations.end()) { if (animationEntryCached == animations.end()) {
this->CacheAnimations(animationKey); this->CacheAnimations(animationKey);
} }
auto animationEntry = this->animations.find(animationKey); auto animationEntry = animations.find(animationKey);
// If we have only one animation, return it regardless of the chance to play. // If we have only one animation, return it regardless of the chance to play.
if (animationEntry->second.size() == 1) { if (animationEntry->second.size() == 1) {
return CDAnimationLookupResult(animationEntry->second.front()); return animationEntry->second.front();
} }
auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1); auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1);
for (auto& animationEntry : animationEntry->second) { for (auto& animationEntry : animationEntry->second) {
randomAnimation -= animationEntry.chance_to_play; randomAnimation -= animationEntry.chance_to_play;
// This is how the client gets the random animation. // This is how the client gets the random animation.
if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return CDAnimationLookupResult(animationEntry); if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return animationEntry;
} }
return CDAnimationLookupResult(); return std::nullopt;
} }

View File

@ -2,6 +2,11 @@
#include "CDTable.h" #include "CDTable.h"
#include <list> #include <list>
#include <optional>
typedef int32_t AnimationGroupID;
typedef std::string AnimationID;
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
struct CDAnimation { struct CDAnimation {
// uint32_t animationGroupID; // uint32_t animationGroupID;
@ -20,12 +25,7 @@ struct CDAnimation {
UNUSED_COLUMN(float blendTime;) //!< The blend time UNUSED_COLUMN(float blendTime;) //!< The blend time
}; };
typedef LookupResult<CDAnimation> CDAnimationLookupResult; class CDAnimationsTable : public CDTable<CDAnimationsTable, std::map<CDAnimationKey, std::list<CDAnimation>>> {
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
typedef int32_t AnimationGroupID;
typedef std::string AnimationID;
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
/** /**
@ -38,7 +38,7 @@ public:
* @param animationGroupID The animationGroupID to lookup * @param animationGroupID The animationGroupID to lookup
* @return CDAnimationLookupResult * @return CDAnimationLookupResult
*/ */
[[nodiscard]] CDAnimationLookupResult GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID); [[nodiscard]] std::optional<CDAnimation> GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID);
/** /**
* Cache a full AnimationGroup by its ID. * Cache a full AnimationGroup by its ID.
@ -58,10 +58,4 @@ private:
* @return false * @return false
*/ */
bool CacheData(CppSQLite3Statement& queryToCache); bool CacheData(CppSQLite3Statement& queryToCache);
/**
* Each animation is key'd by its animationName and its animationGroupID. Each
* animation has a possible list of animations. This is because there can be animations have a percent chance to play so one is selected at random.
*/
std::map<CDAnimationKey, std::list<CDAnimation>> animations;
}; };

View File

@ -1,6 +1,10 @@
#include "CDBehaviorParameterTable.h" #include "CDBehaviorParameterTable.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
namespace {
std::unordered_map<std::string, uint32_t> m_ParametersList;
};
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) { uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
uint64_t key = behaviorID; uint64_t key = behaviorID;
key <<= 31U; key <<= 31U;
@ -11,6 +15,7 @@ uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
void CDBehaviorParameterTable::LoadValuesFromDatabase() { void CDBehaviorParameterTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
uint32_t behaviorID = tableData.getIntField("behaviorID", -1); uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", "")); auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
@ -24,7 +29,7 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
uint64_t hash = GetKey(behaviorID, parameterId); uint64_t hash = GetKey(behaviorID, parameterId);
float value = tableData.getFloatField("value", -1.0f); float value = tableData.getFloatField("value", -1.0f);
m_Entries.insert(std::make_pair(hash, value)); entries.insert(std::make_pair(hash, value));
tableData.nextRow(); tableData.nextRow();
} }
@ -32,22 +37,24 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
} }
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
auto parameterID = this->m_ParametersList.find(name); auto parameterID = m_ParametersList.find(name);
if (parameterID == this->m_ParametersList.end()) return defaultValue; if (parameterID == m_ParametersList.end()) return defaultValue;
auto hash = GetKey(behaviorID, parameterID->second); auto hash = GetKey(behaviorID, parameterID->second);
// Search for specific parameter // Search for specific parameter
auto it = m_Entries.find(hash); auto& entries = GetEntriesMutable();
return it != m_Entries.end() ? it->second : defaultValue; auto it = entries.find(hash);
return it != entries.end() ? it->second : defaultValue;
} }
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
auto& entries = GetEntriesMutable();
uint64_t hashBase = behaviorID; uint64_t hashBase = behaviorID;
std::map<std::string, float> returnInfo; std::map<std::string, float> returnInfo;
for (auto& [parameterString, parameterId] : m_ParametersList) { for (auto& [parameterString, parameterId] : m_ParametersList) {
uint64_t hash = GetKey(hashBase, parameterId); uint64_t hash = GetKey(hashBase, parameterId);
auto infoCandidate = m_Entries.find(hash); auto infoCandidate = entries.find(hash);
if (infoCandidate != m_Entries.end()) { if (infoCandidate != entries.end()) {
returnInfo.insert(std::make_pair(parameterString, infoCandidate->second)); returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
} }
} }

View File

@ -5,12 +5,10 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> { typedef uint64_t BehaviorParameterHash;
private: typedef float BehaviorParameterValue;
typedef uint64_t BehaviorParameterHash;
typedef float BehaviorParameterValue; class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable, std::unordered_map<BehaviorParameterHash, BehaviorParameterValue>> {
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
std::unordered_map<std::string, uint32_t> m_ParametersList;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();

View File

@ -1,5 +1,9 @@
#include "CDBehaviorTemplateTable.h" #include "CDBehaviorTemplateTable.h"
namespace {
std::unordered_set<std::string> m_EffectHandles;
};
void CDBehaviorTemplateTable::LoadValuesFromDatabase() { void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -13,11 +17,9 @@ void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size
this->entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorTemplate");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDBehaviorTemplate entry; CDBehaviorTemplate entry;
entry.behaviorID = tableData.getIntField("behaviorID", -1); entry.behaviorID = tableData.getIntField("behaviorID", -1);
@ -31,30 +33,17 @@ void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first; entry.effectHandle = m_EffectHandles.insert(candidateToAdd).first;
} }
this->entries.push_back(entry); entries.insert(std::make_pair(entry.behaviorID, entry));
this->entriesMappedByBehaviorID.insert(std::make_pair(entry.behaviorID, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<bool(CDBehaviorTemplate)> predicate) {
std::vector<CDBehaviorTemplate> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate)
>> cpplinq::to_vector();
return data;
}
const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
return this->entries;
}
const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) { const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behaviorID) {
auto entry = this->entriesMappedByBehaviorID.find(behaviorID); auto& entries = GetEntriesMutable();
if (entry == this->entriesMappedByBehaviorID.end()) { auto entry = entries.find(behaviorID);
if (entry == entries.end()) {
CDBehaviorTemplate entryToReturn; CDBehaviorTemplate entryToReturn;
entryToReturn.behaviorID = 0; entryToReturn.behaviorID = 0;
entryToReturn.effectHandle = m_EffectHandles.end(); entryToReturn.effectHandle = m_EffectHandles.end();

View File

@ -12,19 +12,9 @@ struct CDBehaviorTemplate {
std::unordered_set<std::string>::iterator effectHandle; //!< The effect handle std::unordered_set<std::string>::iterator effectHandle; //!< The effect handle
}; };
class CDBehaviorTemplateTable : public CDTable<CDBehaviorTemplateTable, std::unordered_map<uint32_t, CDBehaviorTemplate>> {
class CDBehaviorTemplateTable : public CDTable<CDBehaviorTemplateTable> {
private:
std::vector<CDBehaviorTemplate> entries;
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
std::unordered_set<std::string> m_EffectHandles;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
const std::vector<CDBehaviorTemplate>& GetEntries(void) const;
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID); const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
}; };

View File

@ -14,7 +14,8 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BrickIDTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BrickIDTable");
@ -23,7 +24,7 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
entry.NDObjectID = tableData.getIntField("NDObjectID", -1); entry.NDObjectID = tableData.getIntField("NDObjectID", -1);
entry.LEGOBrickID = tableData.getIntField("LEGOBrickID", -1); entry.LEGOBrickID = tableData.getIntField("LEGOBrickID", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -31,15 +32,9 @@ void CDBrickIDTableTable::LoadValuesFromDatabase() {
} }
std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBrickIDTable)> predicate) { std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBrickIDTable)> predicate) {
std::vector<CDBrickIDTable> data = cpplinq::from(GetEntries())
std::vector<CDBrickIDTable> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
return this->entries;
}

View File

@ -16,14 +16,9 @@ struct CDBrickIDTable {
//! BrickIDTable table //! BrickIDTable table
class CDBrickIDTableTable : public CDTable<CDBrickIDTableTable> { class CDBrickIDTableTable : public CDTable<CDBrickIDTableTable, std::vector<CDBrickIDTable>> {
private:
std::vector<CDBrickIDTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate); std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
const std::vector<CDBrickIDTable>& GetEntries() const;
}; };

View File

@ -4,14 +4,15 @@
void CDComponentsRegistryTable::LoadValuesFromDatabase() { void CDComponentsRegistryTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDComponentsRegistry entry; CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0)); entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
entry.component_id = tableData.getIntField("component_id", -1); entry.component_id = tableData.getIntField("component_id", -1);
this->mappedEntries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id); entries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id);
this->mappedEntries.insert_or_assign(entry.id, 0); entries.insert_or_assign(entry.id, 0);
tableData.nextRow(); tableData.nextRow();
} }
@ -20,10 +21,11 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
} }
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) { int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
auto exists = mappedEntries.find(id); auto& entries = GetEntriesMutable();
if (exists != mappedEntries.end()) { auto exists = entries.find(id);
auto iter = mappedEntries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id)); if (exists != entries.end()) {
return iter == mappedEntries.end() ? defaultValue : iter->second; auto iter = entries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id));
return iter == entries.end() ? defaultValue : iter->second;
} }
// Now get the data. Get all components of this entity so we dont do a query for each component // Now get the data. Get all components of this entity so we dont do a query for each component
@ -38,14 +40,14 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0)); entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
entry.component_id = tableData.getIntField("component_id", -1); entry.component_id = tableData.getIntField("component_id", -1);
this->mappedEntries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id); entries.insert_or_assign(static_cast<uint64_t>(entry.component_type) << 32 | static_cast<uint64_t>(entry.id), entry.component_id);
tableData.nextRow(); tableData.nextRow();
} }
mappedEntries.insert_or_assign(id, 0); entries.insert_or_assign(id, 0);
auto iter = this->mappedEntries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id)); auto iter = entries.find(static_cast<uint64_t>(componentType) << 32 | static_cast<uint64_t>(id));
return iter == this->mappedEntries.end() ? defaultValue : iter->second; return iter == entries.end() ? defaultValue : iter->second;
} }

View File

@ -13,10 +13,7 @@ struct CDComponentsRegistry {
}; };
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> { class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable, std::unordered_map<uint64_t, uint32_t>> {
private:
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0); int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);

View File

@ -15,7 +15,8 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM CurrencyTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM CurrencyTable");
@ -27,7 +28,7 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
entry.maxvalue = tableData.getIntField("maxvalue", -1); entry.maxvalue = tableData.getIntField("maxvalue", -1);
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,15 +36,9 @@ void CDCurrencyTableTable::LoadValuesFromDatabase() {
} }
std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCurrencyTable)> predicate) { std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCurrencyTable)> predicate) {
std::vector<CDCurrencyTable> data = cpplinq::from(GetEntries())
std::vector<CDCurrencyTable> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
return this->entries;
}

View File

@ -18,14 +18,9 @@ struct CDCurrencyTable {
}; };
//! CurrencyTable table //! CurrencyTable table
class CDCurrencyTableTable : public CDTable<CDCurrencyTableTable> { class CDCurrencyTableTable : public CDTable<CDCurrencyTableTable, std::vector<CDCurrencyTable>> {
private:
std::vector<CDCurrencyTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate); std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
const std::vector<CDCurrencyTable>& GetEntries() const;
}; };

View File

@ -13,7 +13,8 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DestructibleComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DestructibleComponent");
@ -34,7 +35,7 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
entry.isSmashable = tableData.getIntField("isSmashable", -1) == 1 ? true : false; entry.isSmashable = tableData.getIntField("isSmashable", -1) == 1 ? true : false;
entry.difficultyLevel = tableData.getIntField("difficultyLevel", -1); entry.difficultyLevel = tableData.getIntField("difficultyLevel", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -42,15 +43,9 @@ void CDDestructibleComponentTable::LoadValuesFromDatabase() {
} }
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::function<bool(CDDestructibleComponent)> predicate) { std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::function<bool(CDDestructibleComponent)> predicate) {
std::vector<CDDestructibleComponent> data = cpplinq::from(GetEntries())
std::vector<CDDestructibleComponent> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -20,14 +20,9 @@ struct CDDestructibleComponent {
int32_t difficultyLevel; //!< ??? int32_t difficultyLevel; //!< ???
}; };
class CDDestructibleComponentTable : public CDTable<CDDestructibleComponentTable> { class CDDestructibleComponentTable : public CDTable<CDDestructibleComponentTable, std::vector<CDDestructibleComponent>> {
private:
std::vector<CDDestructibleComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate); std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
const std::vector<CDDestructibleComponent>& GetEntries(void) const;
}; };

View File

@ -2,6 +2,7 @@
void CDEmoteTableTable::LoadValuesFromDatabase() { void CDEmoteTableTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDEmoteTable entry; CDEmoteTable entry;
entry.ID = tableData.getIntField("id", -1); entry.ID = tableData.getIntField("id", -1);
@ -21,6 +22,7 @@ void CDEmoteTableTable::LoadValuesFromDatabase() {
} }
CDEmoteTable* CDEmoteTableTable::GetEmote(int32_t id) { CDEmoteTable* CDEmoteTableTable::GetEmote(int32_t id) {
auto& entries = GetEntriesMutable();
auto itr = entries.find(id); auto itr = entries.find(id);
return itr != entries.end() ? &itr->second : nullptr; return itr != entries.end() ? &itr->second : nullptr;
} }

View File

@ -26,10 +26,7 @@ struct CDEmoteTable {
std::string gateVersion; std::string gateVersion;
}; };
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> { class CDEmoteTableTable : public CDTable<CDEmoteTableTable, std::map<int, CDEmoteTable>> {
private:
std::map<int, CDEmoteTable> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Returns an emote by ID // Returns an emote by ID

View File

@ -14,7 +14,8 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM FeatureGating"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM FeatureGating");
@ -26,7 +27,7 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
entry.minor = tableData.getIntField("minor", -1); entry.minor = tableData.getIntField("minor", -1);
entry.description = tableData.getStringField("description", ""); entry.description = tableData.getStringField("description", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -35,7 +36,8 @@ void CDFeatureGatingTable::LoadValuesFromDatabase() {
std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFeatureGating)> predicate) { std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFeatureGating)> predicate) {
std::vector<CDFeatureGating> data = cpplinq::from(this->entries) auto& entries = GetEntriesMutable();
std::vector<CDFeatureGating> data = cpplinq::from(entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
@ -43,6 +45,7 @@ std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFe
} }
bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const { bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const {
auto& entries = GetEntriesMutable();
for (const auto& entry : entries) { for (const auto& entry : entries) {
if (entry.featureName == feature.featureName && feature >= entry) { if (entry.featureName == feature.featureName && feature >= entry) {
return true; return true;
@ -51,8 +54,3 @@ bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const
return false; return false;
} }
const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
return this->entries;
}

View File

@ -17,10 +17,7 @@ struct CDFeatureGating {
} }
}; };
class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable> { class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable, std::vector<CDFeatureGating>> {
private:
std::vector<CDFeatureGating> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
@ -28,6 +25,4 @@ public:
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate); std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
bool FeatureUnlocked(const CDFeatureGating& feature) const; bool FeatureUnlocked(const CDFeatureGating& feature) const;
const std::vector<CDFeatureGating>& GetEntries(void) const;
}; };

View File

@ -14,7 +14,8 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM InventoryComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM InventoryComponent");
@ -25,7 +26,7 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
entry.count = tableData.getIntField("count", -1); entry.count = tableData.getIntField("count", -1);
entry.equip = tableData.getIntField("equip", -1) == 1 ? true : false; entry.equip = tableData.getIntField("equip", -1) == 1 ? true : false;
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -33,15 +34,9 @@ void CDInventoryComponentTable::LoadValuesFromDatabase() {
} }
std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function<bool(CDInventoryComponent)> predicate) { std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function<bool(CDInventoryComponent)> predicate) {
std::vector<CDInventoryComponent> data = cpplinq::from(GetEntries())
std::vector<CDInventoryComponent> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -10,14 +10,9 @@ struct CDInventoryComponent {
bool equip; //!< Whether or not to equip the item bool equip; //!< Whether or not to equip the item
}; };
class CDInventoryComponentTable : public CDTable<CDInventoryComponentTable> { class CDInventoryComponentTable : public CDTable<CDInventoryComponentTable, std::vector<CDInventoryComponent>> {
private:
std::vector<CDInventoryComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate); std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
const std::vector<CDInventoryComponent>& GetEntries() const;
}; };

View File

@ -17,6 +17,7 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDItemComponent entry; CDItemComponent entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -62,7 +63,7 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
entry.forgeType = tableData.getIntField("forgeType", -1); entry.forgeType = tableData.getIntField("forgeType", -1);
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f); entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
@ -70,8 +71,9 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
} }
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) { const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skillID) {
const auto& it = this->entries.find(skillID); auto& entries = GetEntriesMutable();
if (it != this->entries.end()) { const auto& it = entries.find(skillID);
if (it != entries.end()) {
return it->second; return it->second;
} }
@ -129,12 +131,12 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(uint32_t skill
entry.forgeType = tableData.getIntField("forgeType", -1); entry.forgeType = tableData.getIntField("forgeType", -1);
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f); entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
const auto& it2 = this->entries.find(skillID); const auto& it2 = entries.find(skillID);
if (it2 != this->entries.end()) { if (it2 != entries.end()) {
return it2->second; return it2->second;
} }

View File

@ -49,10 +49,7 @@ struct CDItemComponent {
float SellMultiplier; //!< Something to do with early vendors perhaps (but replaced) float SellMultiplier; //!< Something to do with early vendors perhaps (but replaced)
}; };
class CDItemComponentTable : public CDTable<CDItemComponentTable> { class CDItemComponentTable : public CDTable<CDItemComponentTable, std::map<uint32_t, CDItemComponent>> {
private:
std::map<uint32_t, CDItemComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent); static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);

View File

@ -14,7 +14,8 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSetSkills"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSetSkills");
@ -24,7 +25,7 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
entry.SkillID = tableData.getIntField("SkillID", -1); entry.SkillID = tableData.getIntField("SkillID", -1);
entry.SkillCastType = tableData.getIntField("SkillCastType", -1); entry.SkillCastType = tableData.getIntField("SkillCastType", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -32,22 +33,17 @@ void CDItemSetSkillsTable::LoadValuesFromDatabase() {
} }
std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDItemSetSkills)> predicate) { std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDItemSetSkills)> predicate) {
std::vector<CDItemSetSkills> data = cpplinq::from(GetEntries())
std::vector<CDItemSetSkills> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
return this->entries;
}
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(uint32_t SkillSetID) { std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetBySkillID(uint32_t SkillSetID) {
std::vector<CDItemSetSkills> toReturn; std::vector<CDItemSetSkills> toReturn;
for (CDItemSetSkills entry : this->entries) { for (const auto& entry : GetEntries()) {
if (entry.SkillSetID == SkillSetID) toReturn.push_back(entry); if (entry.SkillSetID == SkillSetID) toReturn.push_back(entry);
if (entry.SkillSetID > SkillSetID) return toReturn; //stop seeking in the db if it's not needed. if (entry.SkillSetID > SkillSetID) return toReturn; //stop seeking in the db if it's not needed.
} }

View File

@ -9,16 +9,11 @@ struct CDItemSetSkills {
uint32_t SkillCastType; //!< The skill cast type uint32_t SkillCastType; //!< The skill cast type
}; };
class CDItemSetSkillsTable : public CDTable<CDItemSetSkillsTable> { class CDItemSetSkillsTable : public CDTable<CDItemSetSkillsTable, std::vector<CDItemSetSkills>> {
private:
std::vector<CDItemSetSkills> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate); std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
const std::vector<CDItemSetSkills>& GetEntries() const;
std::vector<CDItemSetSkills> GetBySkillID(uint32_t SkillSetID); std::vector<CDItemSetSkills> GetBySkillID(uint32_t SkillSetID);
}; };

View File

@ -14,7 +14,8 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSets"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ItemSets");
@ -36,7 +37,7 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
entry.kitID = tableData.getIntField("kitID", -1); entry.kitID = tableData.getIntField("kitID", -1);
entry.priority = tableData.getFloatField("priority", -1.0f); entry.priority = tableData.getFloatField("priority", -1.0f);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -45,14 +46,9 @@ void CDItemSetsTable::LoadValuesFromDatabase() {
std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> predicate) { std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> predicate) {
std::vector<CDItemSets> data = cpplinq::from(this->entries) std::vector<CDItemSets> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
return this->entries;
}

View File

@ -21,15 +21,10 @@ struct CDItemSets {
float priority; //!< The priority float priority; //!< The priority
}; };
class CDItemSetsTable : public CDTable<CDItemSetsTable> { class CDItemSetsTable : public CDTable<CDItemSetsTable, std::vector<CDItemSets>> {
private:
std::vector<CDItemSets> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate); std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
const std::vector<CDItemSets>& GetEntries(void) const;
}; };

View File

@ -14,7 +14,8 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LevelProgressionLookup"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LevelProgressionLookup");
@ -24,7 +25,7 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
entry.requiredUScore = tableData.getIntField("requiredUScore", -1); entry.requiredUScore = tableData.getIntField("requiredUScore", -1);
entry.BehaviorEffect = tableData.getStringField("BehaviorEffect", ""); entry.BehaviorEffect = tableData.getStringField("BehaviorEffect", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -33,14 +34,9 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) { std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries) std::vector<CDLevelProgressionLookup> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
return this->entries;
}

View File

@ -9,15 +9,10 @@ struct CDLevelProgressionLookup {
std::string BehaviorEffect; //!< The behavior effect attached to this std::string BehaviorEffect; //!< The behavior effect attached to this
}; };
class CDLevelProgressionLookupTable : public CDTable<CDLevelProgressionLookupTable> { class CDLevelProgressionLookupTable : public CDTable<CDLevelProgressionLookupTable, std::vector<CDLevelProgressionLookup>> {
private:
std::vector<CDLevelProgressionLookup> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate); std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
const std::vector<CDLevelProgressionLookup>& GetEntries() const;
}; };

View File

@ -25,7 +25,8 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
} }
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
@ -33,14 +34,15 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
CDLootMatrix entry; CDLootMatrix entry;
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
this->entries[lootMatrixIndex].push_back(ReadRow(tableData)); entries[lootMatrixIndex].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
} }
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) { const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
auto itr = this->entries.find(matrixId); auto& entries = GetEntriesMutable();
if (itr != this->entries.end()) { auto itr = entries.find(matrixId);
if (itr != entries.end()) {
return itr->second; return itr->second;
} }
@ -49,10 +51,10 @@ const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
auto tableData = query.execQuery(); auto tableData = query.execQuery();
while (!tableData.eof()) { while (!tableData.eof()) {
this->entries[matrixId].push_back(ReadRow(tableData)); entries[matrixId].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
return this->entries[matrixId]; return entries[matrixId];
} }

View File

@ -16,7 +16,7 @@ struct CDLootMatrix {
typedef uint32_t LootMatrixIndex; typedef uint32_t LootMatrixIndex;
typedef std::vector<CDLootMatrix> LootMatrixEntries; typedef std::vector<CDLootMatrix> LootMatrixEntries;
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> { class CDLootMatrixTable : public CDTable<CDLootMatrixTable, std::unordered_map<LootMatrixIndex, LootMatrixEntries>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
@ -24,6 +24,5 @@ public:
const LootMatrixEntries& GetMatrix(uint32_t matrixId); const LootMatrixEntries& GetMatrix(uint32_t matrixId);
private: private:
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const; CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
}; };

View File

@ -6,8 +6,8 @@
// Sort the tables by their rarity so the highest rarity items are first. // Sort the tables by their rarity so the highest rarity items are first.
void SortTable(LootTableEntries& table) { void SortTable(LootTableEntries& table) {
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>(); auto* componentsRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>(); auto* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
// We modify the table in place so the outer loop keeps track of what is sorted // We modify the table in place so the outer loop keeps track of what is sorted
// and the inner loop finds the highest rarity item and swaps it with the current position // and the inner loop finds the highest rarity item and swaps it with the current position
// of the outer loop. // of the outer loop.
@ -49,7 +49,8 @@ void CDLootTableTable::LoadValuesFromDatabase() {
} }
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
@ -57,17 +58,18 @@ void CDLootTableTable::LoadValuesFromDatabase() {
CDLootTable entry; CDLootTable entry;
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1); uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
this->entries[lootTableIndex].push_back(ReadRow(tableData)); entries[lootTableIndex].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
for (auto& [id, table] : this->entries) { for (auto& [id, table] : entries) {
SortTable(table); SortTable(table);
} }
} }
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) { const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
auto itr = this->entries.find(tableId); auto& entries = GetEntriesMutable();
if (itr != this->entries.end()) { auto itr = entries.find(tableId);
if (itr != entries.end()) {
return itr->second; return itr->second;
} }
@ -77,10 +79,10 @@ const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
while (!tableData.eof()) { while (!tableData.eof()) {
CDLootTable entry; CDLootTable entry;
this->entries[tableId].push_back(ReadRow(tableData)); entries[tableId].push_back(ReadRow(tableData));
tableData.nextRow(); tableData.nextRow();
} }
SortTable(this->entries[tableId]); SortTable(entries[tableId]);
return this->entries[tableId]; return entries[tableId];
} }

View File

@ -13,10 +13,9 @@ struct CDLootTable {
typedef uint32_t LootTableIndex; typedef uint32_t LootTableIndex;
typedef std::vector<CDLootTable> LootTableEntries; typedef std::vector<CDLootTable> LootTableEntries;
class CDLootTableTable : public CDTable<CDLootTableTable> { class CDLootTableTable : public CDTable<CDLootTableTable, std::unordered_map<LootTableIndex, LootTableEntries>> {
private: private:
CDLootTable ReadRow(CppSQLite3Query& tableData) const; CDLootTable ReadRow(CppSQLite3Query& tableData) const;
std::unordered_map<LootTableIndex, LootTableEntries> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();

View File

@ -1,7 +1,7 @@
#include "CDMissionEmailTable.h" #include "CDMissionEmailTable.h"
void CDMissionEmailTable::LoadValuesFromDatabase() {
void CDMissionEmailTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM MissionEmail"); auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM MissionEmail");
@ -14,7 +14,8 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail");
@ -29,7 +30,7 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
entry.locStatus = tableData.getIntField("locStatus", -1); entry.locStatus = tableData.getIntField("locStatus", -1);
entry.gate_version = tableData.getStringField("gate_version", ""); entry.gate_version = tableData.getStringField("gate_version", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -38,15 +39,9 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMissionEmail)> predicate) { std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMissionEmail)> predicate) {
std::vector<CDMissionEmail> data = cpplinq::from(GetEntries())
std::vector<CDMissionEmail> data = cpplinq::from(this->entries)
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
return this->entries;
}

View File

@ -15,14 +15,9 @@ struct CDMissionEmail {
}; };
class CDMissionEmailTable : public CDTable<CDMissionEmailTable> { class CDMissionEmailTable : public CDTable<CDMissionEmailTable, std::vector<CDMissionEmail>> {
private:
std::vector<CDMissionEmail> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate); std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
const std::vector<CDMissionEmail>& GetEntries() const;
}; };

View File

@ -14,7 +14,8 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent");
@ -26,7 +27,7 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false; entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false;
entry.gate_version = tableData.getStringField("gate_version", ""); entry.gate_version = tableData.getStringField("gate_version", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -36,15 +37,9 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::function<bool(CDMissionNPCComponent)> predicate) { std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::function<bool(CDMissionNPCComponent)> predicate) {
std::vector<CDMissionNPCComponent> data = cpplinq::from(this->entries) std::vector<CDMissionNPCComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -11,17 +11,10 @@ struct CDMissionNPCComponent {
std::string gate_version; //!< The gate version std::string gate_version; //!< The gate version
}; };
class CDMissionNPCComponentTable : public CDTable<CDMissionNPCComponentTable> { class CDMissionNPCComponentTable : public CDTable<CDMissionNPCComponentTable, std::vector<CDMissionNPCComponent>> {
private:
std::vector<CDMissionNPCComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate); std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
// Gets all the entries in the table
const std::vector<CDMissionNPCComponent>& GetEntries() const;
}; };

View File

@ -14,7 +14,8 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks");
@ -34,7 +35,7 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false); UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false);
UNUSED(entry.gate_version = tableData.getStringField("gate_version", "")); UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -43,7 +44,7 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) { std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) {
std::vector<CDMissionTasks> data = cpplinq::from(this->entries) std::vector<CDMissionTasks> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
@ -53,7 +54,8 @@ std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMiss
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) { std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) {
std::vector<CDMissionTasks*> tasks; std::vector<CDMissionTasks*> tasks;
for (auto& entry : this->entries) { // TODO: this should not be linear(?) and also shouldnt need to be a pointer
for (auto& entry : GetEntriesMutable()) {
if (entry.id == missionID) { if (entry.id == missionID) {
tasks.push_back(&entry); tasks.push_back(&entry);
} }
@ -62,7 +64,6 @@ std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missio
return tasks; return tasks;
} }
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const { const typename CDMissionTasksTable::StorageType& CDMissionTasksTable::GetEntries() const {
return this->entries; return CDTable::GetEntries();
} }

View File

@ -19,10 +19,7 @@ struct CDMissionTasks {
UNUSED(std::string gate_version); //!< ??? UNUSED(std::string gate_version); //!< ???
}; };
class CDMissionTasksTable : public CDTable<CDMissionTasksTable> { class CDMissionTasksTable : public CDTable<CDMissionTasksTable, std::vector<CDMissionTasks>> {
private:
std::vector<CDMissionTasks> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
@ -30,6 +27,7 @@ public:
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID); std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
const std::vector<CDMissionTasks>& GetEntries() const; // TODO: Remove this and replace it with a proper lookup function.
const CDTable::StorageType& GetEntries() const;
}; };

View File

@ -16,7 +16,8 @@ void CDMissionsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions");
@ -75,7 +76,7 @@ void CDMissionsTable::LoadValuesFromDatabase() {
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1)); UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1); entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -86,19 +87,15 @@ void CDMissionsTable::LoadValuesFromDatabase() {
std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> predicate) { std::vector<CDMissions> CDMissionsTable::Query(std::function<bool(CDMissions)> predicate) {
std::vector<CDMissions> data = cpplinq::from(this->entries) std::vector<CDMissions> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDMissions>& CDMissionsTable::GetEntries(void) const {
return this->entries;
}
const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const { const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == missionID) { if (entry.id == missionID) {
return const_cast<CDMissions*>(&entry); return const_cast<CDMissions*>(&entry);
} }
@ -108,7 +105,7 @@ const CDMissions* CDMissionsTable::GetPtrByMissionID(uint32_t missionID) const {
} }
const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const { const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& found) const {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == missionID) { if (entry.id == missionID) {
found = true; found = true;

View File

@ -60,18 +60,12 @@ struct CDMissions {
int32_t reward_bankinventory; //!< The amount of bank space this mission rewards int32_t reward_bankinventory; //!< The amount of bank space this mission rewards
}; };
class CDMissionsTable : public CDTable<CDMissionsTable> { class CDMissionsTable : public CDTable<CDMissionsTable, std::vector<CDMissions>> {
private:
std::vector<CDMissions> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate); std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
// Gets all the entries in the table
const std::vector<CDMissions>& GetEntries() const;
const CDMissions* GetPtrByMissionID(uint32_t missionID) const; const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const; const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const;

View File

@ -14,7 +14,8 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent");
@ -29,7 +30,7 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f); entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f);
entry.attachedPath = tableData.getStringField("attachedPath", ""); entry.attachedPath = tableData.getStringField("attachedPath", "");
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -38,14 +39,9 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) { std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries) std::vector<CDMovementAIComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
return this->entries;
}

View File

@ -14,15 +14,9 @@ struct CDMovementAIComponent {
std::string attachedPath; std::string attachedPath;
}; };
class CDMovementAIComponentTable : public CDTable<CDMovementAIComponentTable> { class CDMovementAIComponentTable : public CDTable<CDMovementAIComponentTable, std::vector<CDMovementAIComponent>> {
private:
std::vector<CDMovementAIComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate); std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
// Gets all the entries in the table
const std::vector<CDMovementAIComponent>& GetEntries() const;
}; };

View File

@ -14,7 +14,8 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills");
@ -25,7 +26,7 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
entry.castOnType = tableData.getIntField("castOnType", -1); entry.castOnType = tableData.getIntField("castOnType", -1);
entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1); entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -34,13 +35,9 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) { std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
std::vector<CDObjectSkills> data = cpplinq::from(this->entries) std::vector<CDObjectSkills> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
return this->entries;
}

View File

@ -10,17 +10,10 @@ struct CDObjectSkills {
uint32_t AICombatWeight; //!< ??? uint32_t AICombatWeight; //!< ???
}; };
class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable> { class CDObjectSkillsTable : public CDTable<CDObjectSkillsTable, std::vector<CDObjectSkills>> {
private:
std::vector<CDObjectSkills> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate); std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
// Gets all the entries in the table
const std::vector<CDObjectSkills>& GetEntries() const;
}; };

View File

@ -1,5 +1,9 @@
#include "CDObjectsTable.h" #include "CDObjectsTable.h"
namespace {
CDObjects m_default;
};
void CDObjectsTable::LoadValuesFromDatabase() { void CDObjectsTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
uint32_t size = 0; uint32_t size = 0;
@ -14,6 +18,7 @@ void CDObjectsTable::LoadValuesFromDatabase() {
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDObjects entry; CDObjects entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -31,7 +36,7 @@ void CDObjectsTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");) UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);) UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
@ -41,8 +46,9 @@ void CDObjectsTable::LoadValuesFromDatabase() {
} }
const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) { const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
const auto& it = this->entries.find(LOT); auto& entries = GetEntriesMutable();
if (it != this->entries.end()) { const auto& it = entries.find(LOT);
if (it != entries.end()) {
return it->second; return it->second;
} }
@ -51,7 +57,7 @@ const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
auto tableData = query.execQuery(); auto tableData = query.execQuery();
if (tableData.eof()) { if (tableData.eof()) {
this->entries.insert(std::make_pair(LOT, m_default)); entries.insert(std::make_pair(LOT, m_default));
return m_default; return m_default;
} }
@ -73,7 +79,7 @@ const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
UNUSED(entry.gate_version = tableData.getStringField("gate_version", "")); UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1)); UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1));
this->entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }

View File

@ -20,11 +20,7 @@ struct CDObjects {
UNUSED(uint32_t HQ_valid); //!< Probably used for the Nexus HQ database on LEGOUniverse.com UNUSED(uint32_t HQ_valid); //!< Probably used for the Nexus HQ database on LEGOUniverse.com
}; };
class CDObjectsTable : public CDTable<CDObjectsTable> { class CDObjectsTable : public CDTable<CDObjectsTable, std::map<uint32_t, CDObjects>> {
private:
std::map<uint32_t, CDObjects> entries;
CDObjects m_default;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Gets an entry by ID // Gets an entry by ID

View File

@ -13,8 +13,8 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size auto& entries = GetEntriesMutable();
this->entries.reserve(size); entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent");
@ -24,7 +24,7 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
entry.packageType = tableData.getIntField("packageType", -1); entry.packageType = tableData.getIntField("packageType", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -34,15 +34,9 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<bool(CDPackageComponent)> predicate) { std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<bool(CDPackageComponent)> predicate) {
std::vector<CDPackageComponent> data = cpplinq::from(this->entries) std::vector<CDPackageComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
//! Gets all the entries in the table
const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -9,14 +9,9 @@ struct CDPackageComponent {
uint32_t packageType; uint32_t packageType;
}; };
class CDPackageComponentTable : public CDTable<CDPackageComponentTable> { class CDPackageComponentTable : public CDTable<CDPackageComponentTable, std::vector<CDPackageComponent>> {
private:
std::vector<CDPackageComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate); std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
const std::vector<CDPackageComponent>& GetEntries() const;
}; };

View File

@ -23,10 +23,12 @@ namespace {
void CDPetComponentTable::LoadValuesFromDatabase() { void CDPetComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PetComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PetComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
const uint32_t componentID = tableData.getIntField("id", defaultEntry.id); const uint32_t componentID = tableData.getIntField("id", defaultEntry.id);
auto& entry = m_Entries[componentID]; auto& entry = entries[componentID];
entry.id = componentID; entry.id = componentID;
UNUSED_COLUMN(entry.minTameUpdateTime = tableData.getFloatField("minTameUpdateTime", defaultEntry.minTameUpdateTime)); UNUSED_COLUMN(entry.minTameUpdateTime = tableData.getFloatField("minTameUpdateTime", defaultEntry.minTameUpdateTime));
UNUSED_COLUMN(entry.maxTameUpdateTime = tableData.getFloatField("maxTameUpdateTime", defaultEntry.maxTameUpdateTime)); UNUSED_COLUMN(entry.maxTameUpdateTime = tableData.getFloatField("maxTameUpdateTime", defaultEntry.maxTameUpdateTime));
@ -48,12 +50,13 @@ void CDPetComponentTable::LoadValuesFromDatabase() {
} }
void CDPetComponentTable::LoadValuesFromDefaults() { void CDPetComponentTable::LoadValuesFromDefaults() {
m_Entries.insert(std::make_pair(defaultEntry.id, defaultEntry)); GetEntriesMutable().insert(std::make_pair(defaultEntry.id, defaultEntry));
} }
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) { CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
auto itr = m_Entries.find(componentID); auto& entries = GetEntriesMutable();
if (itr == m_Entries.end()) { auto itr = entries.find(componentID);
if (itr == entries.end()) {
LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID); LOG("Unable to load pet component (ID %i) values from database! Using default values instead.", componentID);
return defaultEntry; return defaultEntry;
} }

View File

@ -21,7 +21,7 @@ struct CDPetComponent {
UNUSED_COLUMN(std::string buffIDs;) UNUSED_COLUMN(std::string buffIDs;)
}; };
class CDPetComponentTable : public CDTable<CDPetComponentTable> { class CDPetComponentTable : public CDTable<CDPetComponentTable, std::map<uint32_t, CDPetComponent>> {
public: public:
/** /**
@ -39,7 +39,4 @@ public:
* @returns A reference to the corresponding table, or the default if one could not be found * @returns A reference to the corresponding table, or the default if one could not be found
*/ */
CDPetComponent& GetByID(const uint32_t componentID); CDPetComponent& GetByID(const uint32_t componentID);
private:
std::map<uint32_t, CDPetComponent> m_Entries;
}; };

View File

@ -2,6 +2,7 @@
void CDPhysicsComponentTable::LoadValuesFromDatabase() { void CDPhysicsComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDPhysicsComponent entry; CDPhysicsComponent entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -21,7 +22,7 @@ void CDPhysicsComponentTable::LoadValuesFromDatabase() {
UNUSED(entry->friction = tableData.getFloatField("friction")); UNUSED(entry->friction = tableData.getFloatField("friction"));
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset")); UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
m_entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
@ -29,7 +30,8 @@ void CDPhysicsComponentTable::LoadValuesFromDatabase() {
} }
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(uint32_t componentID) { CDPhysicsComponent* CDPhysicsComponentTable::GetByID(uint32_t componentID) {
auto itr = m_entries.find(componentID); auto& entries = GetEntriesMutable();
return itr != m_entries.end() ? &itr->second : nullptr; auto itr = entries.find(componentID);
return itr != entries.end() ? &itr->second : nullptr;
} }

View File

@ -21,13 +21,10 @@ struct CDPhysicsComponent {
UNUSED(std::string gravityVolumeAsset); UNUSED(std::string gravityVolumeAsset);
}; };
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> { class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable, std::map<uint32_t, CDPhysicsComponent>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PhysicsComponent"; }; static const std::string GetTableName() { return "PhysicsComponent"; };
CDPhysicsComponent* GetByID(uint32_t componentID); CDPhysicsComponent* GetByID(uint32_t componentID);
private:
std::map<uint32_t, CDPhysicsComponent> m_entries;
}; };

View File

@ -1,5 +1,9 @@
#include "CDPropertyEntranceComponentTable.h" #include "CDPropertyEntranceComponentTable.h"
namespace {
CDPropertyEntranceComponent defaultEntry{};
};
void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() { void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -12,7 +16,8 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyEntranceComponent;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyEntranceComponent;");
while (!tableData.eof()) { while (!tableData.eof()) {
@ -24,7 +29,7 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
tableData.getStringField("groupType", "") tableData.getStringField("groupType", "")
}; };
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -32,11 +37,10 @@ void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
} }
CDPropertyEntranceComponent CDPropertyEntranceComponentTable::GetByID(uint32_t id) { CDPropertyEntranceComponent CDPropertyEntranceComponentTable::GetByID(uint32_t id) {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.id == id) if (entry.id == id)
return entry; return entry;
} }
return defaultEntry; return defaultEntry;
} }

View File

@ -9,15 +9,9 @@ struct CDPropertyEntranceComponent {
std::string groupType; std::string groupType;
}; };
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> { class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable, std::vector<CDPropertyEntranceComponent>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
CDPropertyEntranceComponent GetByID(uint32_t id); CDPropertyEntranceComponent GetByID(uint32_t id);
// Gets all the entries in the table
[[nodiscard]] const std::vector<CDPropertyEntranceComponent>& GetEntries() const { return entries; }
private:
std::vector<CDPropertyEntranceComponent> entries{};
CDPropertyEntranceComponent defaultEntry{};
}; };

View File

@ -1,5 +1,9 @@
#include "CDPropertyTemplateTable.h" #include "CDPropertyTemplateTable.h"
namespace {
CDPropertyTemplate defaultEntry{};
};
void CDPropertyTemplateTable::LoadValuesFromDatabase() { void CDPropertyTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
@ -12,7 +16,8 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyTemplate;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PropertyTemplate;");
while (!tableData.eof()) { while (!tableData.eof()) {
@ -23,7 +28,7 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
tableData.getStringField("spawnName", "") tableData.getStringField("spawnName", "")
}; };
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -31,7 +36,7 @@ void CDPropertyTemplateTable::LoadValuesFromDatabase() {
} }
CDPropertyTemplate CDPropertyTemplateTable::GetByMapID(uint32_t mapID) { CDPropertyTemplate CDPropertyTemplateTable::GetByMapID(uint32_t mapID) {
for (const auto& entry : entries) { for (const auto& entry : GetEntries()) {
if (entry.mapID == mapID) if (entry.mapID == mapID)
return entry; return entry;
} }

View File

@ -8,13 +8,9 @@ struct CDPropertyTemplate {
std::string spawnName; std::string spawnName;
}; };
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> { class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable, std::vector<CDPropertyTemplate>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PropertyTemplate"; };
CDPropertyTemplate GetByMapID(uint32_t mapID); CDPropertyTemplate GetByMapID(uint32_t mapID);
private:
std::vector<CDPropertyTemplate> entries{};
CDPropertyTemplate defaultEntry{};
}; };

View File

@ -14,7 +14,8 @@ void CDProximityMonitorComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ProximityMonitorComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ProximityMonitorComponent");
@ -25,7 +26,7 @@ void CDProximityMonitorComponentTable::LoadValuesFromDatabase() {
entry.LoadOnClient = tableData.getIntField("LoadOnClient", -1); entry.LoadOnClient = tableData.getIntField("LoadOnClient", -1);
entry.LoadOnServer = tableData.getIntField("LoadOnServer", -1); entry.LoadOnServer = tableData.getIntField("LoadOnServer", -1);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -34,14 +35,9 @@ void CDProximityMonitorComponentTable::LoadValuesFromDatabase() {
std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) { std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) {
std::vector<CDProximityMonitorComponent> data = cpplinq::from(this->entries) std::vector<CDProximityMonitorComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDProximityMonitorComponent>& CDProximityMonitorComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -10,14 +10,9 @@ struct CDProximityMonitorComponent {
bool LoadOnServer; bool LoadOnServer;
}; };
class CDProximityMonitorComponentTable : public CDTable<CDProximityMonitorComponentTable> { class CDProximityMonitorComponentTable : public CDTable<CDProximityMonitorComponentTable, std::vector<CDProximityMonitorComponent>> {
private:
std::vector<CDProximityMonitorComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
//! Queries the table with a custom "where" clause //! Queries the table with a custom "where" clause
std::vector<CDProximityMonitorComponent> Query(std::function<bool(CDProximityMonitorComponent)> predicate); std::vector<CDProximityMonitorComponent> Query(std::function<bool(CDProximityMonitorComponent)> predicate);
const std::vector<CDProximityMonitorComponent>& GetEntries() const;
}; };

View File

@ -3,6 +3,7 @@
void CDRailActivatorComponentTable::LoadValuesFromDatabase() { void CDRailActivatorComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RailActivatorComponent;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RailActivatorComponent;");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDRailActivatorComponent entry; CDRailActivatorComponent entry;
@ -36,7 +37,7 @@ void CDRailActivatorComponentTable::LoadValuesFromDatabase() {
entry.showNameBillboard = tableData.getIntField("ShowNameBillboard", 0); entry.showNameBillboard = tableData.getIntField("ShowNameBillboard", 0);
m_Entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -44,7 +45,7 @@ void CDRailActivatorComponentTable::LoadValuesFromDatabase() {
} }
CDRailActivatorComponent CDRailActivatorComponentTable::GetEntryByID(int32_t id) const { CDRailActivatorComponent CDRailActivatorComponentTable::GetEntryByID(int32_t id) const {
for (const auto& entry : m_Entries) { for (const auto& entry : GetEntries()) {
if (entry.id == id) if (entry.id == id)
return entry; return entry;
} }
@ -52,10 +53,6 @@ CDRailActivatorComponent CDRailActivatorComponentTable::GetEntryByID(int32_t id)
return {}; return {};
} }
const std::vector<CDRailActivatorComponent>& CDRailActivatorComponentTable::GetEntries() const {
return m_Entries;
}
std::pair<uint32_t, std::u16string> CDRailActivatorComponentTable::EffectPairFromString(std::string& str) { std::pair<uint32_t, std::u16string> CDRailActivatorComponentTable::EffectPairFromString(std::string& str) {
const auto split = GeneralUtils::SplitString(str, ':'); const auto split = GeneralUtils::SplitString(str, ':');
if (split.size() == 2) { if (split.size() == 2) {

View File

@ -20,13 +20,10 @@ struct CDRailActivatorComponent {
bool showNameBillboard; bool showNameBillboard;
}; };
class CDRailActivatorComponentTable : public CDTable<CDRailActivatorComponentTable> { class CDRailActivatorComponentTable : public CDTable<CDRailActivatorComponentTable, std::vector<CDRailActivatorComponent>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "RailActivatorComponent"; };
[[nodiscard]] CDRailActivatorComponent GetEntryByID(int32_t id) const; [[nodiscard]] CDRailActivatorComponent GetEntryByID(int32_t id) const;
[[nodiscard]] const std::vector<CDRailActivatorComponent>& GetEntries() const;
private: private:
static std::pair<uint32_t, std::u16string> EffectPairFromString(std::string& str); static std::pair<uint32_t, std::u16string> EffectPairFromString(std::string& str);
std::vector<CDRailActivatorComponent> m_Entries{};
}; };

View File

@ -14,7 +14,8 @@ void CDRarityTableTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RarityTable order by randmax desc;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RarityTable order by randmax desc;");
@ -30,5 +31,5 @@ void CDRarityTableTable::LoadValuesFromDatabase() {
} }
const std::vector<CDRarityTable>& CDRarityTableTable::GetRarityTable(uint32_t id) { const std::vector<CDRarityTable>& CDRarityTableTable::GetRarityTable(uint32_t id) {
return entries[id]; return GetEntriesMutable()[id];
} }

View File

@ -6,15 +6,13 @@
struct CDRarityTable { struct CDRarityTable {
float randmax; float randmax;
uint32_t rarity; uint32_t rarity;
typedef uint32_t Index;
}; };
typedef std::vector<CDRarityTable> RarityTable; typedef std::vector<CDRarityTable> RarityTable;
class CDRarityTableTable : public CDTable<CDRarityTableTable> { class CDRarityTableTable : public CDTable<CDRarityTableTable, std::unordered_map<CDRarityTable::Index, std::vector<CDRarityTable>>> {
private:
typedef uint32_t RarityTableIndex;
std::unordered_map<RarityTableIndex, std::vector<CDRarityTable>> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();

View File

@ -14,7 +14,8 @@ void CDRebuildComponentTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RebuildComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RebuildComponent");
@ -31,7 +32,7 @@ void CDRebuildComponentTable::LoadValuesFromDatabase() {
entry.post_imagination_cost = tableData.getIntField("post_imagination_cost", -1); entry.post_imagination_cost = tableData.getIntField("post_imagination_cost", -1);
entry.time_before_smash = tableData.getFloatField("time_before_smash", -1.0f); entry.time_before_smash = tableData.getFloatField("time_before_smash", -1.0f);
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
@ -40,14 +41,9 @@ void CDRebuildComponentTable::LoadValuesFromDatabase() {
std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<bool(CDRebuildComponent)> predicate) { std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<bool(CDRebuildComponent)> predicate) {
std::vector<CDRebuildComponent> data = cpplinq::from(this->entries) std::vector<CDRebuildComponent> data = cpplinq::from(GetEntries())
>> cpplinq::where(predicate) >> cpplinq::where(predicate)
>> cpplinq::to_vector(); >> cpplinq::to_vector();
return data; return data;
} }
const std::vector<CDRebuildComponent>& CDRebuildComponentTable::GetEntries() const {
return this->entries;
}

View File

@ -16,15 +16,10 @@ struct CDRebuildComponent {
float time_before_smash; //!< The time before smash float time_before_smash; //!< The time before smash
}; };
class CDRebuildComponentTable : public CDTable<CDRebuildComponentTable> { class CDRebuildComponentTable : public CDTable<CDRebuildComponentTable, std::vector<CDRebuildComponent>> {
private:
std::vector<CDRebuildComponent> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDRebuildComponent> Query(std::function<bool(CDRebuildComponent)> predicate); std::vector<CDRebuildComponent> Query(std::function<bool(CDRebuildComponent)> predicate);
const std::vector<CDRebuildComponent>& GetEntries() const;
}; };

View File

@ -14,7 +14,8 @@ void CDRewardCodesTable::LoadValuesFromDatabase() {
tableSize.finalize(); tableSize.finalize();
// Reserve the size // Reserve the size
this->entries.reserve(size); auto& entries = GetEntriesMutable();
entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RewardCodes"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RewardCodes");
@ -26,20 +27,20 @@ void CDRewardCodesTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1)); UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1));
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "")); UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", ""));
this->entries.push_back(entry); entries.push_back(entry);
tableData.nextRow(); tableData.nextRow();
} }
} }
LOT CDRewardCodesTable::GetAttachmentLOT(uint32_t rewardCodeId) const { LOT CDRewardCodesTable::GetAttachmentLOT(uint32_t rewardCodeId) const {
for (auto const &entry : this->entries){ for (auto const &entry : GetEntries()){
if (rewardCodeId == entry.id) return entry.attachmentLOT; if (rewardCodeId == entry.id) return entry.attachmentLOT;
} }
return LOT_NULL; return LOT_NULL;
} }
uint32_t CDRewardCodesTable::GetCodeID(std::string code) const { uint32_t CDRewardCodesTable::GetCodeID(std::string code) const {
for (auto const &entry : this->entries){ for (auto const &entry : GetEntries()){
if (code == entry.code) return entry.id; if (code == entry.code) return entry.id;
} }
return -1; return -1;

View File

@ -13,13 +13,9 @@ struct CDRewardCode {
}; };
class CDRewardCodesTable : public CDTable<CDRewardCodesTable> { class CDRewardCodesTable : public CDTable<CDRewardCodesTable, std::vector<CDRewardCode>> {
private:
std::vector<CDRewardCode> entries;
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
const std::vector<CDRewardCode>& GetEntries() const;
LOT GetAttachmentLOT(uint32_t rewardCodeId) const; LOT GetAttachmentLOT(uint32_t rewardCodeId) const;
uint32_t GetCodeID(std::string code) const; uint32_t GetCodeID(std::string code) const;
}; };

View File

@ -2,6 +2,7 @@
void CDRewardsTable::LoadValuesFromDatabase() { void CDRewardsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) { while (!tableData.eof()) {
CDRewards entry; CDRewards entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -11,7 +12,7 @@ void CDRewardsTable::LoadValuesFromDatabase() {
entry.value = tableData.getIntField("value", -1); entry.value = tableData.getIntField("value", -1);
entry.count = tableData.getIntField("count", -1); entry.count = tableData.getIntField("count", -1);
m_entries.insert(std::make_pair(entry.id, entry)); entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
@ -20,7 +21,7 @@ void CDRewardsTable::LoadValuesFromDatabase() {
std::vector<CDRewards> CDRewardsTable::GetByLevelID(uint32_t levelID) { std::vector<CDRewards> CDRewardsTable::GetByLevelID(uint32_t levelID) {
std::vector<CDRewards> result{}; std::vector<CDRewards> result{};
for (const auto& e : m_entries) { for (const auto& e : GetEntries()) {
if (e.second.levelID == levelID) result.push_back(e.second); if (e.second.levelID == levelID) result.push_back(e.second);
} }

View File

@ -11,13 +11,9 @@ struct CDRewards {
int32_t count; int32_t count;
}; };
class CDRewardsTable : public CDTable<CDRewardsTable> { class CDRewardsTable : public CDTable<CDRewardsTable, std::map<uint32_t, CDRewards>> {
public: public:
void LoadValuesFromDatabase(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "Rewards"; };
std::vector<CDRewards> GetByLevelID(uint32_t levelID); std::vector<CDRewards> GetByLevelID(uint32_t levelID);
private:
std::map<uint32_t, CDRewards> m_entries;
}; };

Some files were not shown because too many files have changed in this diff Show More