mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-16 20:24:39 -06:00
Compare commits
64 Commits
copilot/fi
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40fef36530 | ||
|
|
bf020baa17 | ||
|
|
a713216540 | ||
|
|
ea86a708e4 | ||
|
|
ca7424cbeb | ||
|
|
991e55f305 | ||
|
|
5410acffaa | ||
|
|
86f8601bbd | ||
|
|
4658318a3a | ||
| 11d44ffb98 | |||
|
|
2fb16420f3 | ||
|
|
96089a8d9a | ||
|
|
eac50acfcc | ||
|
|
ca60787055 | ||
|
|
396dcb0465 | ||
|
|
6e545eb1b9 | ||
|
|
46aac016fd | ||
|
|
83823fa64f | ||
|
|
0dd504c803 | ||
|
|
a70c365c23 | ||
|
|
281d9762ef | ||
|
|
002aa896d8 | ||
|
|
f3a5f60d81 | ||
|
|
4c9c773ec5 | ||
|
|
ec6253c80c | ||
| c2dba31f70 | |||
|
|
74630b56c8 | ||
|
|
fd6029ae10 | ||
|
|
ff645a6662 | ||
|
|
e051229fb6 | ||
| ce28834dce | |||
|
|
cbdd5d9bc6 | ||
|
|
62ac65c520 | ||
|
|
5d5bce53d0 | ||
|
|
5791c55a9e | ||
|
|
17d0c45382 | ||
|
|
7dbbef81ac | ||
|
|
06958cb9cd | ||
|
|
69b1a694a6 | ||
|
|
b2609ff6cb | ||
|
|
e8c0b3e6da | ||
|
|
25418fd8b2 | ||
|
|
502c965d97 | ||
|
|
205c190c61 | ||
|
|
670cb124c0 | ||
|
|
76c2f380bf | ||
|
|
b5a3cc9187 | ||
|
|
74e1d36bb1 | ||
|
|
64faac714c | ||
|
|
4a5dd68e87 | ||
|
|
4a577f233d | ||
|
|
bb05b3ac0d | ||
|
|
06022e4b19 | ||
|
|
6389876c6e | ||
|
|
68f2e2dee2 | ||
|
|
b798da8ef8 | ||
|
|
154112050f | ||
|
|
6d3bf2fdc3 | ||
|
|
566a18df38 | ||
|
|
f6c13d9ee6 | ||
|
|
8198ad70f6 | ||
|
|
4c3bace601 | ||
|
|
6d2a21450b | ||
|
|
f9e74e6994 |
29
.github/copilot-instructions.md
vendored
Normal file
29
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# GitHub Copilot Instructions
|
||||||
|
|
||||||
|
* c++20 standard, please use the latest features except NO modules.
|
||||||
|
* use `.contains` for searching in associative containers
|
||||||
|
* use const as much as possible. If it can be const, it should be made const
|
||||||
|
* DO NOT USE const_cast EVER.
|
||||||
|
* use `cstdint` bitwidth types ALWAYS for integral types.
|
||||||
|
* NEVER use std::wstring. If wide strings are necessary, use std::u16string with conversion utilties in GeneralUtils.h.
|
||||||
|
* Functions are ALWAYS PascalCase.
|
||||||
|
* local variables are camelCase
|
||||||
|
* NEVER use snake case
|
||||||
|
* indentation is TABS, not SPACES.
|
||||||
|
* TABS are 4 spaces by default
|
||||||
|
* Use trailing braces ALWAYS
|
||||||
|
* global variables are prefixed with `g_`
|
||||||
|
* if global variables or functions are needed, they should be located in an anonymous namespace
|
||||||
|
* Use `GeneralUtils::TryParse` for ANY parsing of strings to integrals.
|
||||||
|
* Use brace initialization when possible.
|
||||||
|
* ALWAYS default initialize variables.
|
||||||
|
* Pointers should be avoided unless necessary. Use references when the pointer has been checked and should not be null
|
||||||
|
* headers should be as compact as possible. Do NOT include extra data that isnt needed.
|
||||||
|
* Remember to include logs (LOG macro uses printf style logging) while putting verbose logs under LOG_DEBUG.
|
||||||
|
* NEVER USE `RakNet::BitStream::ReadBit`
|
||||||
|
* NEVER assume pointers are good, always check if they are null. Once a pointer is checked and is known to be non-null, further accesses no longer need checking
|
||||||
|
* Be wary of TOCTOU. Prevent all possible issues relating to TOCTOU.
|
||||||
|
* new memory allocations should never be used unless absolutely necessary.
|
||||||
|
* new for reconstruction of objects is allowed
|
||||||
|
* Prefer following the format of the file over correct formatting. Consistency over correctness.
|
||||||
|
* When using auto, ALWAYS put a * for pointers.
|
||||||
@@ -19,6 +19,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debuggi
|
|||||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
||||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
set(FETCHCONTENT_QUIET FALSE) # GLM takes a long time to clone, this will at least show _something_ while its downloading
|
||||||
|
|
||||||
# Read variables from file
|
# Read variables from file
|
||||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||||
@@ -306,7 +307,7 @@ add_subdirectory(dServer)
|
|||||||
add_subdirectory(dWeb)
|
add_subdirectory(dWeb)
|
||||||
|
|
||||||
# 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" "magic_enum")
|
set(COMMON_LIBRARIES glm::glm "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||||
|
|
||||||
# Add platform specific common libraries
|
# Add platform specific common libraries
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ FetchContent_Declare(
|
|||||||
googletest
|
googletest
|
||||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
GIT_TAG release-1.12.1
|
GIT_TAG release-1.12.1
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
GIT_SHALLOW 1
|
||||||
)
|
)
|
||||||
|
|
||||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Server::SetupLogger("AuthServer");
|
Server::SetupLogger("AuthServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
Game::config->LogSettings();
|
||||||
|
|
||||||
LOG("Starting Auth server...");
|
LOG("Starting Auth server...");
|
||||||
LOG("Version: %s", PROJECT_VERSION);
|
LOG("Version: %s", PROJECT_VERSION);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
|
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
|
||||||
|
|
||||||
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
|
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
|
||||||
target_link_libraries(dChatFilter dDatabase)
|
target_link_libraries(dChatFilter dDatabase glm::glm)
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}
|
|||||||
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||||
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer" "${PROJECT_SOURCE_DIR}/dChatFilter")
|
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer" "${PROJECT_SOURCE_DIR}/dChatFilter")
|
||||||
|
|
||||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter glm::glm)
|
||||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer mongoose dWeb)
|
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer mongoose dWeb)
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
|||||||
if (!receiver.ignoredPlayers.empty()) {
|
if (!receiver.ignoredPlayers.empty()) {
|
||||||
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
|
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
|
||||||
} else {
|
} else {
|
||||||
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
|
auto ignoreList = Database::Get()->GetIgnoreList(playerId);
|
||||||
if (ignoreList.empty()) {
|
if (ignoreList.empty()) {
|
||||||
LOG_DEBUG("Player %llu has no ignores", playerId);
|
LOG_DEBUG("Player %llu has no ignores", playerId);
|
||||||
return;
|
return;
|
||||||
@@ -43,7 +43,6 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
|||||||
for (auto& ignoredPlayer : ignoreList) {
|
for (auto& ignoredPlayer : ignoreList) {
|
||||||
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
|
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
|
||||||
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +113,8 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
||||||
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
|
Database::Get()->AddIgnore(playerId, ignoredPlayerId);
|
||||||
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
|
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
|
||||||
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
@@ -157,7 +155,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
|
Database::Get()->RemoveIgnore(playerId, toRemove->playerId);
|
||||||
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
|
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.isFTP = false; // not a thing in DLU
|
fd.isFTP = false; // not a thing in DLU
|
||||||
fd.friendID = friendData.friendID;
|
fd.friendID = friendData.friendID;
|
||||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::PERSISTENT);
|
|
||||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
@@ -161,9 +160,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
|
|
||||||
// Set the bits
|
// Set the bits
|
||||||
GeneralUtils::SetBit(queryPlayerID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(queryPlayerID, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(queryPlayerID, eObjectBits::PERSISTENT);
|
|
||||||
GeneralUtils::SetBit(queryFriendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(queryFriendID, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(queryFriendID, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
// Since this player can either be the friend of someone else or be friends with someone else
|
// Since this player can either be the friend of someone else or be friends with someone else
|
||||||
// their column in the database determines what bit gets set. When the value hits 3, they
|
// their column in the database determines what bit gets set. When the value hits 3, they
|
||||||
@@ -318,7 +315,6 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert friendID to LWOOBJID
|
// Convert friendID to LWOOBJID
|
||||||
GeneralUtils::SetBit(friendID, eObjectBits::PERSISTENT);
|
|
||||||
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
Database::Get()->RemoveFriend(playerID, friendID);
|
Database::Get()->RemoveFriend(playerID, friendID);
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ int main(int argc, char** argv) {
|
|||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Server::SetupLogger("ChatServer");
|
Server::SetupLogger("ChatServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
Game::config->LogSettings();
|
||||||
|
|
||||||
//Read our config:
|
//Read our config:
|
||||||
|
|
||||||
@@ -201,8 +202,11 @@ int main(int argc, char** argv) {
|
|||||||
//Delete our objects here:
|
//Delete our objects here:
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
|
Game::server = nullptr;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
|
Game::logger = nullptr;
|
||||||
delete Game::config;
|
delete Game::config;
|
||||||
|
Game::config = nullptr;
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ TeamData* TeamContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newTeam->lootFlag = 1;
|
newTeam->lootFlag = 0;
|
||||||
|
|
||||||
TeamStatusUpdate(newTeam);
|
TeamStatusUpdate(newTeam);
|
||||||
|
|
||||||
|
|||||||
@@ -374,6 +374,21 @@ public:
|
|||||||
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AMFArrayValue& PushDebug(const NiPoint3& point) {
|
||||||
|
PushDebug<AMFDoubleValue>("X") = point.x;
|
||||||
|
PushDebug<AMFDoubleValue>("Y") = point.y;
|
||||||
|
PushDebug<AMFDoubleValue>("Z") = point.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
AMFArrayValue& PushDebug(const NiQuaternion& rot) {
|
||||||
|
PushDebug<AMFDoubleValue>("W") = rot.w;
|
||||||
|
PushDebug<AMFDoubleValue>("X") = rot.x;
|
||||||
|
PushDebug<AMFDoubleValue>("Y") = rot.y;
|
||||||
|
PushDebug<AMFDoubleValue>("Z") = rot.z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ elseif (WIN32)
|
|||||||
zlib
|
zlib
|
||||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
GIT_SHALLOW 1
|
||||||
)
|
)
|
||||||
|
|
||||||
# Disable warning about no project version.
|
# Disable warning about no project version.
|
||||||
@@ -74,5 +76,6 @@ else ()
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
target_link_libraries(dCommon
|
target_link_libraries(dCommon
|
||||||
|
PUBLIC glm::glm
|
||||||
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
|
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
|
||||||
INTERFACE dDatabase)
|
INTERFACE dDatabase)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// C++
|
// C++
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -19,6 +19,9 @@
|
|||||||
#include "dPlatforms.h"
|
#include "dPlatforms.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "DluAssert.h"
|
||||||
|
|
||||||
|
#include <glm/ext/vector_float3.hpp>
|
||||||
|
|
||||||
enum eInventoryType : uint32_t;
|
enum eInventoryType : uint32_t;
|
||||||
enum class eObjectBits : size_t;
|
enum class eObjectBits : size_t;
|
||||||
@@ -244,7 +247,7 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
[[nodiscard]] std::optional<T> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||||
const auto x = TryParse<float>(strX);
|
const auto x = TryParse<float>(strX);
|
||||||
if (!x) return std::nullopt;
|
if (!x) return std::nullopt;
|
||||||
|
|
||||||
@@ -252,7 +255,7 @@ namespace GeneralUtils {
|
|||||||
if (!y) return std::nullopt;
|
if (!y) return std::nullopt;
|
||||||
|
|
||||||
const auto z = TryParse<float>(strZ);
|
const auto z = TryParse<float>(strZ);
|
||||||
return z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
|
return z ? std::make_optional<T>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,8 +264,8 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
|
[[nodiscard]] std::optional<T> TryParse(const std::span<const std::string> str) {
|
||||||
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
return (str.size() == 3) ? TryParse<T>(str[0], str[1], str[2]) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -303,7 +306,7 @@ namespace GeneralUtils {
|
|||||||
template<typename Container>
|
template<typename Container>
|
||||||
inline Container::value_type GetRandomElement(const Container& container) {
|
inline Container::value_type GetRandomElement(const Container& container) {
|
||||||
DluAssert(!container.empty());
|
DluAssert(!container.empty());
|
||||||
return container[GenerateRandomNumber<typename Container::value_type>(0, container.size() - 1)];
|
return container[GenerateRandomNumber<typename Container::size_type>(0, container.size() - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -96,3 +96,17 @@ bool Logger::GetLogToConsole() const {
|
|||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuncEntry::FuncEntry(const char* funcName, const char* fileName, const uint32_t line) {
|
||||||
|
m_FuncName = funcName;
|
||||||
|
if (!m_FuncName) m_FuncName = "Unknown";
|
||||||
|
m_Line = line;
|
||||||
|
m_FileName = fileName;
|
||||||
|
LOG("--> %s::%s:%i", m_FileName, m_FuncName, m_Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
FuncEntry::~FuncEntry() {
|
||||||
|
if (!m_FuncName || !m_FileName) return;
|
||||||
|
|
||||||
|
LOG("<-- %s::%s:%i", m_FileName, m_FuncName, m_Line);
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,6 +32,19 @@ constexpr const char* GetFileNameFromAbsolutePath(const char* path) {
|
|||||||
#define LOG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->Log(str_, message, ##__VA_ARGS__); } while(0)
|
#define LOG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->Log(str_, message, ##__VA_ARGS__); } while(0)
|
||||||
#define LOG_DEBUG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->LogDebug(str_, message, ##__VA_ARGS__); } while(0)
|
#define LOG_DEBUG(message, ...) do { auto str_ = FILENAME_AND_LINE; Game::logger->LogDebug(str_, message, ##__VA_ARGS__); } while(0)
|
||||||
|
|
||||||
|
// Place this right at the start of a function. Will log a message when called and then once you leave the function.
|
||||||
|
#define LOG_ENTRY auto str_ = GetFileNameFromAbsolutePath(__FILE__); FuncEntry funcEntry_(__FUNCTION__, str_, __LINE__)
|
||||||
|
|
||||||
|
class FuncEntry {
|
||||||
|
public:
|
||||||
|
FuncEntry(const char* funcName, const char* fileName, const uint32_t line);
|
||||||
|
~FuncEntry();
|
||||||
|
private:
|
||||||
|
const char* m_FuncName = nullptr;
|
||||||
|
const char* m_FileName = nullptr;
|
||||||
|
uint32_t m_Line = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// Writer class for writing data to files.
|
// Writer class for writing data to files.
|
||||||
class Writer {
|
class Writer {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -5,13 +5,43 @@
|
|||||||
#include "TinyXmlUtils.h"
|
#include "TinyXmlUtils.h"
|
||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <functional>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// The base LXFML xml file to use when creating new models.
|
||||||
|
std::string g_base = R"(<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||||
|
<LXFML versionMajor="5" versionMinor="0">
|
||||||
|
<Meta>
|
||||||
|
<Application name="LEGO Universe" versionMajor="0" versionMinor="0"/>
|
||||||
|
<Brand name="LEGOUniverse"/>
|
||||||
|
<BrickSet version="457"/>
|
||||||
|
</Meta>
|
||||||
|
<Bricks>
|
||||||
|
</Bricks>
|
||||||
|
<RigidSystems>
|
||||||
|
</RigidSystems>
|
||||||
|
<GroupSystems>
|
||||||
|
<GroupSystem>
|
||||||
|
</GroupSystem>
|
||||||
|
</GroupSystems>
|
||||||
|
</LXFML>)";
|
||||||
|
}
|
||||||
|
|
||||||
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoint3& curPosition) {
|
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoint3& curPosition) {
|
||||||
Result toReturn;
|
Result toReturn;
|
||||||
|
|
||||||
|
// Handle empty or invalid input
|
||||||
|
if (data.empty()) {
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
tinyxml2::XMLDocument doc;
|
tinyxml2::XMLDocument doc;
|
||||||
const auto err = doc.Parse(data.data());
|
// Use length-based parsing to avoid expensive string copy
|
||||||
|
const auto err = doc.Parse(data.data(), data.size());
|
||||||
if (err != tinyxml2::XML_SUCCESS) {
|
if (err != tinyxml2::XML_SUCCESS) {
|
||||||
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +50,6 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
|
|
||||||
auto lxfml = reader["LXFML"];
|
auto lxfml = reader["LXFML"];
|
||||||
if (!lxfml) {
|
if (!lxfml) {
|
||||||
LOG("Failed to find LXFML element.");
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,16 +78,19 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
// Calculate the lowest and highest points on the entire model
|
// Calculate the lowest and highest points on the entire model
|
||||||
for (const auto& transformation : transformations | std::views::values) {
|
for (const auto& transformation : transformations | std::views::values) {
|
||||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||||
if (split.size() < 12) {
|
if (split.size() < 12) continue;
|
||||||
LOG("Not enough in the split?");
|
|
||||||
continue;
|
auto xOpt = GeneralUtils::TryParse<float>(split[9]);
|
||||||
}
|
auto yOpt = GeneralUtils::TryParse<float>(split[10]);
|
||||||
|
auto zOpt = GeneralUtils::TryParse<float>(split[11]);
|
||||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
|
||||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
if (!xOpt.has_value() || !yOpt.has_value() || !zOpt.has_value()) continue;
|
||||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
|
||||||
if (x < lowest.x) lowest.x = x;
|
auto x = xOpt.value();
|
||||||
if (y < lowest.y) lowest.y = y;
|
auto y = yOpt.value();
|
||||||
|
auto z = zOpt.value();
|
||||||
|
if (x < lowest.x) lowest.x = x;
|
||||||
|
if (y < lowest.y) lowest.y = y;
|
||||||
if (z < lowest.z) lowest.z = z;
|
if (z < lowest.z) lowest.z = z;
|
||||||
|
|
||||||
if (highest.x < x) highest.x = x;
|
if (highest.x < x) highest.x = x;
|
||||||
@@ -87,13 +119,19 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
for (auto& transformation : transformations | std::views::values) {
|
for (auto& transformation : transformations | std::views::values) {
|
||||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||||
if (split.size() < 12) {
|
if (split.size() < 12) {
|
||||||
LOG("Not enough in the split?");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x + curPosition.x;
|
auto xOpt = GeneralUtils::TryParse<float>(split[9]);
|
||||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y + curPosition.y;
|
auto yOpt = GeneralUtils::TryParse<float>(split[10]);
|
||||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z + curPosition.z;
|
auto zOpt = GeneralUtils::TryParse<float>(split[11]);
|
||||||
|
|
||||||
|
if (!xOpt.has_value() || !yOpt.has_value() || !zOpt.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto x = xOpt.value() - newRootPos.x + curPosition.x;
|
||||||
|
auto y = yOpt.value() - newRootPos.y + curPosition.y;
|
||||||
|
auto z = zOpt.value() - newRootPos.z + curPosition.z;
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
stream << split[i];
|
stream << split[i];
|
||||||
@@ -128,3 +166,345 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
|||||||
toReturn.center = newRootPos;
|
toReturn.center = newRootPos;
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deep-clone an XMLElement (attributes, text, and child elements) into a target document
|
||||||
|
// with maximum depth protection to prevent infinite loops
|
||||||
|
static tinyxml2::XMLElement* CloneElementDeep(const tinyxml2::XMLElement* src, tinyxml2::XMLDocument& dstDoc, int maxDepth = 100) {
|
||||||
|
if (!src || maxDepth <= 0) return nullptr;
|
||||||
|
auto* dst = dstDoc.NewElement(src->Name());
|
||||||
|
|
||||||
|
// copy attributes
|
||||||
|
for (const tinyxml2::XMLAttribute* attr = src->FirstAttribute(); attr; attr = attr->Next()) {
|
||||||
|
dst->SetAttribute(attr->Name(), attr->Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy children (elements and text)
|
||||||
|
for (const tinyxml2::XMLNode* child = src->FirstChild(); child; child = child->NextSibling()) {
|
||||||
|
if (const tinyxml2::XMLElement* childElem = child->ToElement()) {
|
||||||
|
// Recursively clone child elements with decremented depth
|
||||||
|
auto* clonedChild = CloneElementDeep(childElem, dstDoc, maxDepth - 1);
|
||||||
|
if (clonedChild) dst->InsertEndChild(clonedChild);
|
||||||
|
} else if (const tinyxml2::XMLText* txt = child->ToText()) {
|
||||||
|
auto* n = dstDoc.NewText(txt->Value());
|
||||||
|
dst->InsertEndChild(n);
|
||||||
|
} else if (const tinyxml2::XMLComment* c = child->ToComment()) {
|
||||||
|
auto* n = dstDoc.NewComment(c->Value());
|
||||||
|
dst->InsertEndChild(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Lxfml::Result> Lxfml::Split(const std::string_view data, const NiPoint3& curPosition) {
|
||||||
|
std::vector<Result> results;
|
||||||
|
|
||||||
|
// Handle empty or invalid input
|
||||||
|
if (data.empty()) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent processing extremely large inputs that could cause hangs
|
||||||
|
if (data.size() > 10000000) { // 10MB limit
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
// Use length-based parsing to avoid expensive string copy
|
||||||
|
const auto err = doc.Parse(data.data(), data.size());
|
||||||
|
if (err != tinyxml2::XML_SUCCESS) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* lxfml = doc.FirstChildElement("LXFML");
|
||||||
|
if (!lxfml) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build maps: partRef -> Part element, partRef -> Brick element, boneRef -> partRef, brickRef -> Brick element
|
||||||
|
std::unordered_map<std::string, tinyxml2::XMLElement*> partRefToPart;
|
||||||
|
std::unordered_map<std::string, tinyxml2::XMLElement*> partRefToBrick;
|
||||||
|
std::unordered_map<std::string, std::string> boneRefToPartRef;
|
||||||
|
std::unordered_map<std::string, tinyxml2::XMLElement*> brickByRef;
|
||||||
|
|
||||||
|
auto* bricksParent = lxfml->FirstChildElement("Bricks");
|
||||||
|
if (bricksParent) {
|
||||||
|
for (auto* brick = bricksParent->FirstChildElement("Brick"); brick; brick = brick->NextSiblingElement("Brick")) {
|
||||||
|
const char* brickRef = brick->Attribute("refID");
|
||||||
|
if (brickRef) brickByRef.emplace(std::string(brickRef), brick);
|
||||||
|
for (auto* part = brick->FirstChildElement("Part"); part; part = part->NextSiblingElement("Part")) {
|
||||||
|
const char* partRef = part->Attribute("refID");
|
||||||
|
if (partRef) {
|
||||||
|
partRefToPart.emplace(std::string(partRef), part);
|
||||||
|
partRefToBrick.emplace(std::string(partRef), brick);
|
||||||
|
}
|
||||||
|
auto* bone = part->FirstChildElement("Bone");
|
||||||
|
if (bone) {
|
||||||
|
const char* boneRef = bone->Attribute("refID");
|
||||||
|
if (boneRef) boneRefToPartRef.emplace(std::string(boneRef), partRef ? std::string(partRef) : std::string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect RigidSystem elements
|
||||||
|
std::vector<tinyxml2::XMLElement*> rigidSystems;
|
||||||
|
auto* rigidSystemsParent = lxfml->FirstChildElement("RigidSystems");
|
||||||
|
if (rigidSystemsParent) {
|
||||||
|
for (auto* rs = rigidSystemsParent->FirstChildElement("RigidSystem"); rs; rs = rs->NextSiblingElement("RigidSystem")) {
|
||||||
|
rigidSystems.push_back(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect top-level groups (immediate children of GroupSystem)
|
||||||
|
std::vector<tinyxml2::XMLElement*> groupRoots;
|
||||||
|
auto* groupSystemsParent = lxfml->FirstChildElement("GroupSystems");
|
||||||
|
if (groupSystemsParent) {
|
||||||
|
for (auto* gs = groupSystemsParent->FirstChildElement("GroupSystem"); gs; gs = gs->NextSiblingElement("GroupSystem")) {
|
||||||
|
for (auto* group = gs->FirstChildElement("Group"); group; group = group->NextSiblingElement("Group")) {
|
||||||
|
groupRoots.push_back(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track used bricks and rigidsystems
|
||||||
|
std::unordered_set<std::string> usedBrickRefs;
|
||||||
|
std::unordered_set<tinyxml2::XMLElement*> usedRigidSystems;
|
||||||
|
|
||||||
|
// Track used groups to avoid processing them twice
|
||||||
|
std::unordered_set<tinyxml2::XMLElement*> usedGroups;
|
||||||
|
|
||||||
|
// Helper to create output document from sets of brick refs and rigidsystem pointers
|
||||||
|
auto makeOutput = [&](const std::unordered_set<std::string>& bricksToInclude, const std::vector<tinyxml2::XMLElement*>& rigidSystemsToInclude, const std::vector<tinyxml2::XMLElement*>& groupsToInclude = {}) {
|
||||||
|
tinyxml2::XMLDocument outDoc;
|
||||||
|
outDoc.Parse(g_base.c_str());
|
||||||
|
auto* outRoot = outDoc.FirstChildElement("LXFML");
|
||||||
|
auto* outBricks = outRoot->FirstChildElement("Bricks");
|
||||||
|
auto* outRigidSystems = outRoot->FirstChildElement("RigidSystems");
|
||||||
|
auto* outGroupSystems = outRoot->FirstChildElement("GroupSystems");
|
||||||
|
|
||||||
|
// clone and insert bricks
|
||||||
|
for (const auto& bref : bricksToInclude) {
|
||||||
|
auto it = brickByRef.find(bref);
|
||||||
|
if (it == brickByRef.end()) continue;
|
||||||
|
tinyxml2::XMLElement* cloned = CloneElementDeep(it->second, outDoc);
|
||||||
|
if (cloned) outBricks->InsertEndChild(cloned);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone and insert rigidsystems
|
||||||
|
for (auto* rsPtr : rigidSystemsToInclude) {
|
||||||
|
tinyxml2::XMLElement* cloned = CloneElementDeep(rsPtr, outDoc);
|
||||||
|
if (cloned) outRigidSystems->InsertEndChild(cloned);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clone and insert group(s) if requested
|
||||||
|
if (outGroupSystems && !groupsToInclude.empty()) {
|
||||||
|
// clear default children
|
||||||
|
while (outGroupSystems->FirstChild()) outGroupSystems->DeleteChild(outGroupSystems->FirstChild());
|
||||||
|
// create a GroupSystem element and append requested groups
|
||||||
|
auto* newGS = outDoc.NewElement("GroupSystem");
|
||||||
|
for (auto* gptr : groupsToInclude) {
|
||||||
|
tinyxml2::XMLElement* clonedG = CloneElementDeep(gptr, outDoc);
|
||||||
|
if (clonedG) newGS->InsertEndChild(clonedG);
|
||||||
|
}
|
||||||
|
outGroupSystems->InsertEndChild(newGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print to string
|
||||||
|
tinyxml2::XMLPrinter printer;
|
||||||
|
outDoc.Print(&printer);
|
||||||
|
// Normalize position and compute center using existing helper
|
||||||
|
std::string xmlString = printer.CStr();
|
||||||
|
if (xmlString.size() > 5000000) { // 5MB limit for normalization
|
||||||
|
Result emptyResult;
|
||||||
|
emptyResult.lxfml = xmlString;
|
||||||
|
return emptyResult;
|
||||||
|
}
|
||||||
|
auto normalized = NormalizePosition(xmlString, curPosition);
|
||||||
|
return normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1) Process groups (each top-level Group becomes one output; nested groups are included)
|
||||||
|
for (auto* groupRoot : groupRoots) {
|
||||||
|
// Skip if this group was already processed as part of another group
|
||||||
|
if (usedGroups.find(groupRoot) != usedGroups.end()) continue;
|
||||||
|
|
||||||
|
// Helper to collect all partRefs in a group's subtree
|
||||||
|
std::function<void(const tinyxml2::XMLElement*, std::unordered_set<std::string>&)> collectParts = [&](const tinyxml2::XMLElement* g, std::unordered_set<std::string>& partRefs) {
|
||||||
|
if (!g) return;
|
||||||
|
const char* partAttr = g->Attribute("partRefs");
|
||||||
|
if (partAttr) {
|
||||||
|
for (auto& tok : GeneralUtils::SplitString(partAttr, ',')) partRefs.insert(tok);
|
||||||
|
}
|
||||||
|
for (auto* child = g->FirstChildElement("Group"); child; child = child->NextSiblingElement("Group")) collectParts(child, partRefs);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collect all groups that need to be merged into this output
|
||||||
|
std::vector<tinyxml2::XMLElement*> groupsToInclude{ groupRoot };
|
||||||
|
usedGroups.insert(groupRoot);
|
||||||
|
|
||||||
|
// Build initial sets of bricks and boneRefs from the starting group
|
||||||
|
std::unordered_set<std::string> partRefs;
|
||||||
|
collectParts(groupRoot, partRefs);
|
||||||
|
|
||||||
|
std::unordered_set<std::string> bricksIncluded;
|
||||||
|
std::unordered_set<std::string> boneRefsIncluded;
|
||||||
|
for (const auto& pref : partRefs) {
|
||||||
|
auto pit = partRefToBrick.find(pref);
|
||||||
|
if (pit != partRefToBrick.end()) {
|
||||||
|
const char* bref = pit->second->Attribute("refID");
|
||||||
|
if (bref) bricksIncluded.insert(std::string(bref));
|
||||||
|
}
|
||||||
|
auto partIt = partRefToPart.find(pref);
|
||||||
|
if (partIt != partRefToPart.end()) {
|
||||||
|
auto* bone = partIt->second->FirstChildElement("Bone");
|
||||||
|
if (bone) {
|
||||||
|
const char* bref = bone->Attribute("refID");
|
||||||
|
if (bref) boneRefsIncluded.insert(std::string(bref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iteratively include any RigidSystems that reference any boneRefsIncluded
|
||||||
|
// and check if those rigid systems' bricks span other groups
|
||||||
|
bool changed = true;
|
||||||
|
std::vector<tinyxml2::XMLElement*> rigidSystemsToInclude;
|
||||||
|
int maxIterations = 1000; // Safety limit to prevent infinite loops
|
||||||
|
int iteration = 0;
|
||||||
|
while (changed && iteration < maxIterations) {
|
||||||
|
changed = false;
|
||||||
|
iteration++;
|
||||||
|
|
||||||
|
// First, expand rigid systems based on current boneRefsIncluded
|
||||||
|
for (auto* rs : rigidSystems) {
|
||||||
|
if (usedRigidSystems.find(rs) != usedRigidSystems.end()) continue;
|
||||||
|
// parse boneRefs of this rigid system (from its <Rigid> children)
|
||||||
|
bool intersects = false;
|
||||||
|
std::vector<std::string> rsBoneRefs;
|
||||||
|
for (auto* rigid = rs->FirstChildElement("Rigid"); rigid; rigid = rigid->NextSiblingElement("Rigid")) {
|
||||||
|
const char* battr = rigid->Attribute("boneRefs");
|
||||||
|
if (!battr) continue;
|
||||||
|
for (auto& tok : GeneralUtils::SplitString(battr, ',')) {
|
||||||
|
rsBoneRefs.push_back(tok);
|
||||||
|
if (boneRefsIncluded.find(tok) != boneRefsIncluded.end()) intersects = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!intersects) continue;
|
||||||
|
// include this rigid system and all boneRefs it references
|
||||||
|
usedRigidSystems.insert(rs);
|
||||||
|
rigidSystemsToInclude.push_back(rs);
|
||||||
|
for (const auto& br : rsBoneRefs) {
|
||||||
|
boneRefsIncluded.insert(br);
|
||||||
|
auto bpIt = boneRefToPartRef.find(br);
|
||||||
|
if (bpIt != boneRefToPartRef.end()) {
|
||||||
|
auto partRef = bpIt->second;
|
||||||
|
auto pbIt = partRefToBrick.find(partRef);
|
||||||
|
if (pbIt != partRefToBrick.end()) {
|
||||||
|
const char* bref = pbIt->second->Attribute("refID");
|
||||||
|
if (bref && bricksIncluded.insert(std::string(bref)).second) changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second, check if the newly included bricks span any other groups
|
||||||
|
// If so, merge those groups into the current output
|
||||||
|
for (auto* otherGroup : groupRoots) {
|
||||||
|
if (usedGroups.find(otherGroup) != usedGroups.end()) continue;
|
||||||
|
|
||||||
|
// Collect partRefs from this other group
|
||||||
|
std::unordered_set<std::string> otherPartRefs;
|
||||||
|
collectParts(otherGroup, otherPartRefs);
|
||||||
|
|
||||||
|
// Check if any of these partRefs correspond to bricks we've already included
|
||||||
|
bool spansOtherGroup = false;
|
||||||
|
for (const auto& pref : otherPartRefs) {
|
||||||
|
auto pit = partRefToBrick.find(pref);
|
||||||
|
if (pit != partRefToBrick.end()) {
|
||||||
|
const char* bref = pit->second->Attribute("refID");
|
||||||
|
if (bref && bricksIncluded.find(std::string(bref)) != bricksIncluded.end()) {
|
||||||
|
spansOtherGroup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spansOtherGroup) {
|
||||||
|
// Merge this group into the current output
|
||||||
|
usedGroups.insert(otherGroup);
|
||||||
|
groupsToInclude.push_back(otherGroup);
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
// Add all partRefs, boneRefs, and bricks from this group
|
||||||
|
for (const auto& pref : otherPartRefs) {
|
||||||
|
auto pit = partRefToBrick.find(pref);
|
||||||
|
if (pit != partRefToBrick.end()) {
|
||||||
|
const char* bref = pit->second->Attribute("refID");
|
||||||
|
if (bref) bricksIncluded.insert(std::string(bref));
|
||||||
|
}
|
||||||
|
auto partIt = partRefToPart.find(pref);
|
||||||
|
if (partIt != partRefToPart.end()) {
|
||||||
|
auto* bone = partIt->second->FirstChildElement("Bone");
|
||||||
|
if (bone) {
|
||||||
|
const char* bref = bone->Attribute("refID");
|
||||||
|
if (bref) boneRefsIncluded.insert(std::string(bref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iteration >= maxIterations) {
|
||||||
|
// Iteration limit reached, stop processing to prevent infinite loops
|
||||||
|
// The file is likely malformed, so just skip further processing
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
// include bricks from bricksIncluded into used set
|
||||||
|
for (const auto& b : bricksIncluded) usedBrickRefs.insert(b);
|
||||||
|
|
||||||
|
// make output doc and push result (include all merged groups' XML)
|
||||||
|
auto normalized = makeOutput(bricksIncluded, rigidSystemsToInclude, groupsToInclude);
|
||||||
|
results.push_back(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Process remaining RigidSystems (each becomes its own file)
|
||||||
|
for (auto* rs : rigidSystems) {
|
||||||
|
if (usedRigidSystems.find(rs) != usedRigidSystems.end()) continue;
|
||||||
|
std::unordered_set<std::string> bricksIncluded;
|
||||||
|
// collect boneRefs referenced by this rigid system
|
||||||
|
for (auto* rigid = rs->FirstChildElement("Rigid"); rigid; rigid = rigid->NextSiblingElement("Rigid")) {
|
||||||
|
const char* battr = rigid->Attribute("boneRefs");
|
||||||
|
if (!battr) continue;
|
||||||
|
for (auto& tok : GeneralUtils::SplitString(battr, ',')) {
|
||||||
|
auto bpIt = boneRefToPartRef.find(tok);
|
||||||
|
if (bpIt != boneRefToPartRef.end()) {
|
||||||
|
auto partRef = bpIt->second;
|
||||||
|
auto pbIt = partRefToBrick.find(partRef);
|
||||||
|
if (pbIt != partRefToBrick.end()) {
|
||||||
|
const char* bref = pbIt->second->Attribute("refID");
|
||||||
|
if (bref) bricksIncluded.insert(std::string(bref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mark used
|
||||||
|
for (const auto& b : bricksIncluded) usedBrickRefs.insert(b);
|
||||||
|
usedRigidSystems.insert(rs);
|
||||||
|
|
||||||
|
std::vector<tinyxml2::XMLElement*> rsVec{ rs };
|
||||||
|
auto normalized = makeOutput(bricksIncluded, rsVec);
|
||||||
|
results.push_back(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Any remaining bricks not included become their own files
|
||||||
|
for (const auto& [bref, brickPtr] : brickByRef) {
|
||||||
|
if (usedBrickRefs.find(bref) != usedBrickRefs.end()) continue;
|
||||||
|
std::unordered_set<std::string> bricksIncluded{ bref };
|
||||||
|
auto normalized = makeOutput(bricksIncluded, {});
|
||||||
|
results.push_back(normalized);
|
||||||
|
usedBrickRefs.insert(bref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ namespace Lxfml {
|
|||||||
// Normalizes a LXFML model to be positioned relative to its local 0, 0, 0 rather than a game worlds 0, 0, 0.
|
// Normalizes a LXFML model to be positioned relative to its local 0, 0, 0 rather than a game worlds 0, 0, 0.
|
||||||
// Returns a struct of its new center and the updated LXFML containing these edits.
|
// Returns a struct of its new center and the updated LXFML containing these edits.
|
||||||
[[nodiscard]] Result NormalizePosition(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
[[nodiscard]] Result NormalizePosition(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
||||||
|
[[nodiscard]] std::vector<Result> Split(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
||||||
|
|
||||||
// these are only for the migrations due to a bug in one of the implementations.
|
// these are only for the migrations due to a bug in one of the implementations.
|
||||||
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
||||||
|
|||||||
@@ -6,10 +6,14 @@
|
|||||||
\brief Defines a point in space in XYZ coordinates
|
\brief Defines a point in space in XYZ coordinates
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class NiPoint3;
|
class NiPoint3;
|
||||||
class NiQuaternion;
|
|
||||||
typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoint3 class, but typedef'd for clarity in some cases
|
typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoint3 class, but typedef'd for clarity in some cases
|
||||||
|
|
||||||
|
#include <glm/ext/vector_float3.hpp>
|
||||||
|
|
||||||
|
#include "NiQuaternion.h"
|
||||||
|
|
||||||
//! A custom class the defines a point in space
|
//! A custom class the defines a point in space
|
||||||
class NiPoint3 {
|
class NiPoint3 {
|
||||||
public:
|
public:
|
||||||
@@ -21,6 +25,12 @@ public:
|
|||||||
//! Initializer
|
//! Initializer
|
||||||
constexpr NiPoint3() = default;
|
constexpr NiPoint3() = default;
|
||||||
|
|
||||||
|
constexpr NiPoint3(const glm::vec3& vec) noexcept
|
||||||
|
: x{ vec.x }
|
||||||
|
, y{ vec.y }
|
||||||
|
, z{ vec.z } {
|
||||||
|
}
|
||||||
|
|
||||||
//! Initializer
|
//! Initializer
|
||||||
/*!
|
/*!
|
||||||
\param x The x coordinate
|
\param x The x coordinate
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "NiQuaternion.h"
|
#include "NiQuaternion.h"
|
||||||
|
#include <glm/ext/quaternion_float.hpp>
|
||||||
|
|
||||||
// MARK: Getters / Setters
|
// MARK: Getters / Setters
|
||||||
|
|
||||||
|
|||||||
@@ -3,37 +3,18 @@
|
|||||||
// C++
|
// C++
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
// MARK: Member Functions
|
// MARK: Member Functions
|
||||||
|
|
||||||
Vector3 NiQuaternion::GetEulerAngles() const {
|
Vector3 QuatUtils::Euler(const NiQuaternion& quat) {
|
||||||
Vector3 angles;
|
return glm::eulerAngles(quat);
|
||||||
|
|
||||||
// roll (x-axis rotation)
|
|
||||||
const float sinr_cosp = 2 * (w * x + y * z);
|
|
||||||
const float cosr_cosp = 1 - 2 * (x * x + y * y);
|
|
||||||
angles.x = std::atan2(sinr_cosp, cosr_cosp);
|
|
||||||
|
|
||||||
// pitch (y-axis rotation)
|
|
||||||
const float sinp = 2 * (w * y - z * x);
|
|
||||||
|
|
||||||
if (std::abs(sinp) >= 1) {
|
|
||||||
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
|
|
||||||
} else {
|
|
||||||
angles.y = std::asin(sinp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// yaw (z-axis rotation)
|
|
||||||
const float siny_cosp = 2 * (w * z + x * y);
|
|
||||||
const float cosy_cosp = 1 - 2 * (y * y + z * z);
|
|
||||||
angles.z = std::atan2(siny_cosp, cosy_cosp);
|
|
||||||
|
|
||||||
return angles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Helper Functions
|
// MARK: Helper Functions
|
||||||
|
|
||||||
//! Look from a specific point in space to another point in space (Y-locked)
|
//! Look from a specific point in space to another point in space (Y-locked)
|
||||||
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
NiQuaternion QuatUtils::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;
|
||||||
NiPoint3 dest = destPoint;
|
NiPoint3 dest = destPoint;
|
||||||
@@ -51,11 +32,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
|
|||||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||||
|
|
||||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Look from a specific point in space to another point in space
|
//! Look from a specific point in space to another point in space
|
||||||
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
NiQuaternion QuatUtils::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||||
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
||||||
|
|
||||||
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
||||||
@@ -67,37 +48,26 @@ NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiP
|
|||||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||||
|
|
||||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||||
}
|
}
|
||||||
|
|
||||||
//! 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
|
||||||
NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle) {
|
NiQuaternion QuatUtils::AxisAngle(const Vector3& axis, float angle) {
|
||||||
float halfAngle = angle * 0.5f;
|
return glm::angleAxis(angle, glm::vec3(axis.x, axis.y, axis.z));
|
||||||
float s = static_cast<float>(sin(halfAngle));
|
|
||||||
|
|
||||||
NiQuaternion q;
|
|
||||||
q.x = axis.GetX() * s;
|
|
||||||
q.y = axis.GetY() * s;
|
|
||||||
q.z = axis.GetZ() * s;
|
|
||||||
q.w = static_cast<float>(cos(halfAngle));
|
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
|
NiQuaternion QuatUtils::FromEuler(const NiPoint3& eulerAngles) {
|
||||||
// Abbreviations for the various angular functions
|
return glm::quat(glm::vec3(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
||||||
float cy = cos(eulerAngles.z * 0.5);
|
}
|
||||||
float sy = sin(eulerAngles.z * 0.5);
|
|
||||||
float cp = cos(eulerAngles.y * 0.5);
|
Vector3 QuatUtils::Forward(const NiQuaternion& quat) {
|
||||||
float sp = sin(eulerAngles.y * 0.5);
|
return quat * glm::vec3(0, 0, 1);
|
||||||
float cr = cos(eulerAngles.x * 0.5);
|
}
|
||||||
float sr = sin(eulerAngles.x * 0.5);
|
|
||||||
|
Vector3 QuatUtils::Up(const NiQuaternion& quat) {
|
||||||
NiQuaternion q;
|
return quat * glm::vec3(0, 1, 0);
|
||||||
q.w = cr * cp * cy + sr * sp * sy;
|
}
|
||||||
q.x = sr * cp * cy - cr * sp * sy;
|
|
||||||
q.y = cr * sp * cy + sr * cp * sy;
|
Vector3 QuatUtils::Right(const NiQuaternion& quat) {
|
||||||
q.z = cr * cp * sy - sr * sp * cy;
|
return quat * glm::vec3(1, 0, 0);
|
||||||
|
|
||||||
return q;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,158 +1,27 @@
|
|||||||
#ifndef __NIQUATERNION_H__
|
#ifndef NIQUATERNION_H
|
||||||
#define __NIQUATERNION_H__
|
#define NIQUATERNION_H
|
||||||
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
/*!
|
#define GLM_FORCE_QUAT_DATA_WXYZ
|
||||||
\file NiQuaternion.hpp
|
|
||||||
\brief Defines a quaternion in space in WXYZ coordinates
|
|
||||||
*/
|
|
||||||
|
|
||||||
class NiQuaternion;
|
#include <glm/ext/quaternion_float.hpp>
|
||||||
typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version of NiQuaternion
|
|
||||||
|
|
||||||
//! A class that defines a rotation in space
|
using Quaternion = glm::quat;
|
||||||
class NiQuaternion {
|
using NiQuaternion = Quaternion;
|
||||||
public:
|
|
||||||
float w{ 1 }; //!< The w coordinate
|
|
||||||
float x{ 0 }; //!< The x coordinate
|
|
||||||
float y{ 0 }; //!< The y coordinate
|
|
||||||
float z{ 0 }; //!< The z coordinate
|
|
||||||
|
|
||||||
|
namespace QuatUtils {
|
||||||
//! The initializer
|
constexpr NiQuaternion IDENTITY = glm::identity<NiQuaternion>();
|
||||||
constexpr NiQuaternion() = default;
|
Vector3 Forward(const NiQuaternion& quat);
|
||||||
|
Vector3 Up(const NiQuaternion& quat);
|
||||||
//! The initializer
|
Vector3 Right(const NiQuaternion& quat);
|
||||||
/*!
|
NiQuaternion LookAt(const NiPoint3& from, const NiPoint3& to);
|
||||||
\param w The w coordinate
|
NiQuaternion LookAtUnlocked(const NiPoint3& from, const NiPoint3& to);
|
||||||
\param x The x coordinate
|
Vector3 Euler(const NiQuaternion& quat);
|
||||||
\param y The y coordinate
|
NiQuaternion AxisAngle(const Vector3& axis, float angle);
|
||||||
\param z The z coordinate
|
NiQuaternion FromEuler(const NiPoint3& eulerAngles);
|
||||||
*/
|
constexpr float PI_OVER_180 = glm::pi<float>() / 180.0f;
|
||||||
constexpr NiQuaternion(const float w, const float x, const float y, const float z) noexcept
|
|
||||||
: w{ w }
|
|
||||||
, x{ x }
|
|
||||||
, y{ y }
|
|
||||||
, z{ z } {
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Setters / Getters
|
|
||||||
|
|
||||||
//! Gets the W coordinate
|
|
||||||
/*!
|
|
||||||
\return The w coordinate
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr float GetW() const noexcept;
|
|
||||||
|
|
||||||
//! Sets the W coordinate
|
|
||||||
/*!
|
|
||||||
\param w The w coordinate
|
|
||||||
*/
|
|
||||||
constexpr void SetW(const float w) noexcept;
|
|
||||||
|
|
||||||
//! Gets the X coordinate
|
|
||||||
/*!
|
|
||||||
\return The x coordinate
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr float GetX() const noexcept;
|
|
||||||
|
|
||||||
//! Sets the X coordinate
|
|
||||||
/*!
|
|
||||||
\param x The x coordinate
|
|
||||||
*/
|
|
||||||
constexpr void SetX(const float x) noexcept;
|
|
||||||
|
|
||||||
//! Gets the Y coordinate
|
|
||||||
/*!
|
|
||||||
\return The y coordinate
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr float GetY() const noexcept;
|
|
||||||
|
|
||||||
//! Sets the Y coordinate
|
|
||||||
/*!
|
|
||||||
\param y The y coordinate
|
|
||||||
*/
|
|
||||||
constexpr void SetY(const float y) noexcept;
|
|
||||||
|
|
||||||
//! Gets the Z coordinate
|
|
||||||
/*!
|
|
||||||
\return The z coordinate
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr float GetZ() const noexcept;
|
|
||||||
|
|
||||||
//! Sets the Z coordinate
|
|
||||||
/*!
|
|
||||||
\param z The z coordinate
|
|
||||||
*/
|
|
||||||
constexpr void SetZ(const float z) noexcept;
|
|
||||||
|
|
||||||
// MARK: Member Functions
|
|
||||||
|
|
||||||
//! Returns the forward vector from the quaternion
|
|
||||||
/*!
|
|
||||||
\return The forward vector of the quaternion
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr Vector3 GetForwardVector() const noexcept;
|
|
||||||
|
|
||||||
//! Returns the up vector from the quaternion
|
|
||||||
/*!
|
|
||||||
\return The up vector fo the quaternion
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr Vector3 GetUpVector() const noexcept;
|
|
||||||
|
|
||||||
//! Returns the right vector from the quaternion
|
|
||||||
/*!
|
|
||||||
\return The right vector of the quaternion
|
|
||||||
*/
|
|
||||||
[[nodiscard]] constexpr Vector3 GetRightVector() const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] Vector3 GetEulerAngles() const;
|
|
||||||
|
|
||||||
// MARK: Operators
|
|
||||||
|
|
||||||
//! Operator to check for equality
|
|
||||||
constexpr bool operator==(const NiQuaternion& rot) const noexcept;
|
|
||||||
|
|
||||||
//! Operator to check for inequality
|
|
||||||
constexpr bool operator!=(const NiQuaternion& rot) const noexcept;
|
|
||||||
|
|
||||||
// MARK: Helper Functions
|
|
||||||
|
|
||||||
//! Look from a specific point in space to another point in space (Y-locked)
|
|
||||||
/*!
|
|
||||||
\param sourcePoint The source location
|
|
||||||
\param destPoint The destination location
|
|
||||||
\return The Quaternion with the rotation towards the destination
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
|
||||||
|
|
||||||
//! Look from a specific point in space to another point in space
|
|
||||||
/*!
|
|
||||||
\param sourcePoint The source location
|
|
||||||
\param destPoint The destination location
|
|
||||||
\return The Quaternion with the rotation towards the destination
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
|
||||||
|
|
||||||
//! Creates a Quaternion from a specific axis and angle relative to that axis
|
|
||||||
/*!
|
|
||||||
\param axis The axis that is used
|
|
||||||
\param angle The angle relative to this axis
|
|
||||||
\return A quaternion created from the axis and angle
|
|
||||||
*/
|
|
||||||
[[nodiscard]] static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
|
|
||||||
|
|
||||||
[[nodiscard]] static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static Variables
|
#endif // !NIQUATERNION_H
|
||||||
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__
|
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ struct LocalSpaceInfo {
|
|||||||
|
|
||||||
struct PositionUpdate {
|
struct PositionUpdate {
|
||||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||||
bool onGround = false;
|
bool onGround = false;
|
||||||
bool onRail = false;
|
bool onRail = false;
|
||||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ public:
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
AssetStream GetFile(const char* name) const;
|
AssetStream GetFile(const char* name) const;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
AssetStream GetFile(const std::string& name) const { return GetFile(name.c_str()); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadPackIndex();
|
void LoadPackIndex();
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ void dConfig::LoadConfig() {
|
|||||||
void dConfig::ReloadConfig() {
|
void dConfig::ReloadConfig() {
|
||||||
this->m_ConfigValues.clear();
|
this->m_ConfigValues.clear();
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
|
for (const auto& handler : m_ConfigHandlers) handler();
|
||||||
|
LogSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& dConfig::GetValue(std::string key) {
|
const std::string& dConfig::GetValue(std::string key) {
|
||||||
@@ -58,6 +60,18 @@ const std::string& dConfig::GetValue(std::string key) {
|
|||||||
return this->m_ConfigValues[key];
|
return this->m_ConfigValues[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dConfig::AddConfigHandler(std::function<void()> handler) {
|
||||||
|
m_ConfigHandlers.push_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dConfig::LogSettings() const {
|
||||||
|
LOG("Configuration settings:");
|
||||||
|
for (const auto& [key, value] : m_ConfigValues) {
|
||||||
|
const auto& valueLog = key.find("password") != std::string::npos ? "<HIDDEN>" : value;
|
||||||
|
LOG(" %s = %s", key.c_str(), valueLog.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dConfig::ProcessLine(const std::string& line) {
|
void dConfig::ProcessLine(const std::string& line) {
|
||||||
auto splitLoc = line.find('=');
|
auto splitLoc = line.find('=');
|
||||||
auto key = line.substr(0, splitLoc);
|
auto key = line.substr(0, splitLoc);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -29,10 +31,15 @@ public:
|
|||||||
* Reloads the config file to reset values
|
* Reloads the config file to reset values
|
||||||
*/
|
*/
|
||||||
void ReloadConfig();
|
void ReloadConfig();
|
||||||
|
|
||||||
|
// Adds a function to be called when the config is (re)loaded
|
||||||
|
void AddConfigHandler(std::function<void()> handler);
|
||||||
|
void LogSettings() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessLine(const std::string& line);
|
void ProcessLine(const std::string& line);
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<std::string, std::string> m_ConfigValues;
|
std::map<std::string, std::string> m_ConfigValues;
|
||||||
|
std::vector<std::function<void()>> m_ConfigHandlers;
|
||||||
std::string m_ConfigFilePath;
|
std::string m_ConfigFilePath;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
namespace MessageType {
|
namespace MessageType {
|
||||||
enum class Master : uint32_t {
|
enum class Master : uint32_t {
|
||||||
REQUEST_PERSISTENT_ID = 1,
|
REQUEST_ZONE_TRANSFER = 1,
|
||||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
|
||||||
REQUEST_ZONE_TRANSFER,
|
|
||||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||||
SERVER_INFO,
|
SERVER_INFO,
|
||||||
REQUEST_SESSION_KEY,
|
REQUEST_SESSION_KEY,
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ enum class eCharacterVersion : uint32_t {
|
|||||||
SPEED_BASE,
|
SPEED_BASE,
|
||||||
// Fixes nexus force explorer missions
|
// Fixes nexus force explorer missions
|
||||||
NJ_JAYMISSIONS,
|
NJ_JAYMISSIONS,
|
||||||
UP_TO_DATE, // will become NEXUS_FORCE_EXPLORER
|
NEXUS_FORCE_EXPLORER, // Fixes pet ids in player inventories
|
||||||
|
PET_IDS, // Fixes pet ids in player inventories
|
||||||
|
UP_TO_DATE, // will become INVENTORY_PERSISTENT_IDS
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ECHARACTERVERSION__H__
|
#endif //!__ECHARACTERVERSION__H__
|
||||||
|
|||||||
@@ -50,7 +50,10 @@ enum class eMissionState : int {
|
|||||||
/**
|
/**
|
||||||
* The mission has been completed before and has now been completed again. Used for daily missions.
|
* The mission has been completed before and has now been completed again. Used for daily missions.
|
||||||
*/
|
*/
|
||||||
COMPLETE_READY_TO_COMPLETE = 12
|
COMPLETE_READY_TO_COMPLETE = 12,
|
||||||
|
|
||||||
|
// The mission is failed (don't know where this is used)
|
||||||
|
FAILED = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__MISSIONSTATE__H__
|
#endif //!__MISSIONSTATE__H__
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
#ifndef __EOBJECTBITS__H__
|
#ifndef EOBJECTBITS_H
|
||||||
#define __EOBJECTBITS__H__
|
#define EOBJECTBITS_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
enum class eObjectBits : size_t {
|
enum class eObjectBits : size_t {
|
||||||
PERSISTENT = 32,
|
|
||||||
CLIENT = 46,
|
CLIENT = 46,
|
||||||
SPAWNED = 58,
|
SPAWNED = 58,
|
||||||
CHARACTER = 60
|
CHARACTER = 60
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__EOBJECTBITS__H__
|
#endif //!EOBJECTBITS_H
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#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;
|
||||||
@@ -56,3 +55,13 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<const CDActivities> CDActivitiesTable::GetActivity(const uint32_t activityID) {
|
||||||
|
auto& entries = GetEntries();
|
||||||
|
for (const auto& entry : entries) {
|
||||||
|
if (entry.ActivityID == activityID) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
struct CDActivities {
|
struct CDActivities {
|
||||||
uint32_t ActivityID;
|
uint32_t ActivityID;
|
||||||
@@ -31,4 +32,5 @@ public:
|
|||||||
|
|
||||||
// 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);
|
||||||
|
std::optional<const CDActivities> GetActivity(const uint32_t activityID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ target_include_directories(dDatabaseCDClient PUBLIC "."
|
|||||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||||
)
|
)
|
||||||
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3)
|
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3 glm::glm)
|
||||||
|
|
||||||
if (${CDCLIENT_CACHE_ALL})
|
if (${CDCLIENT_CACHE_ALL})
|
||||||
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})
|
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ add_dependencies(dDatabase conncpp_dylib)
|
|||||||
|
|
||||||
target_include_directories(dDatabase PUBLIC ".")
|
target_include_directories(dDatabase PUBLIC ".")
|
||||||
target_link_libraries(dDatabase
|
target_link_libraries(dDatabase
|
||||||
PUBLIC dDatabaseCDClient dDatabaseGame)
|
PUBLIC dDatabaseCDClient dDatabaseGame
|
||||||
|
PRIVATE glm::glm)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ target_include_directories(dDatabaseGame PUBLIC "."
|
|||||||
|
|
||||||
target_link_libraries(dDatabaseGame
|
target_link_libraries(dDatabaseGame
|
||||||
INTERFACE dCommon
|
INTERFACE dCommon
|
||||||
PRIVATE sqlite3 MariaDB::ConnCpp)
|
PRIVATE sqlite3 MariaDB::ConnCpp glm::glm)
|
||||||
|
|
||||||
# Glob together all headers that need to be precompiled
|
# Glob together all headers that need to be precompiled
|
||||||
file(
|
file(
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
virtual void Commit() = 0;
|
virtual void Commit() = 0;
|
||||||
virtual bool GetAutoCommit() = 0;
|
virtual bool GetAutoCommit() = 0;
|
||||||
virtual void SetAutoCommit(bool value) = 0;
|
virtual void SetAutoCommit(bool value) = 0;
|
||||||
virtual void DeleteCharacter(const uint32_t characterId) = 0;
|
virtual void DeleteCharacter(const LWOOBJID characterId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__GAMEDATABASE__H__
|
#endif //!__GAMEDATABASE__H__
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public:
|
|||||||
std::string bcryptPassword;
|
std::string bcryptPassword;
|
||||||
uint32_t id{};
|
uint32_t id{};
|
||||||
uint32_t playKeyId{};
|
uint32_t playKeyId{};
|
||||||
|
uint64_t muteExpire{};
|
||||||
bool banned{};
|
bool banned{};
|
||||||
bool locked{};
|
bool locked{};
|
||||||
eGameMasterLevel maxGmLevel{};
|
eGameMasterLevel maxGmLevel{};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ enum class eActivityType : uint32_t {
|
|||||||
class IActivityLog {
|
class IActivityLog {
|
||||||
public:
|
public:
|
||||||
// Update the activity log for the given account.
|
// Update the activity log for the given account.
|
||||||
virtual void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
virtual void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IACTIVITYLOG__H__
|
#endif //!__IACTIVITYLOG__H__
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class IBehaviors {
|
|||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
LWOOBJID behaviorId{};
|
LWOOBJID behaviorId{};
|
||||||
uint32_t characterId{};
|
LWOOBJID characterId{};
|
||||||
std::string behaviorInfo;
|
std::string behaviorInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public:
|
|||||||
std::string clientVersion;
|
std::string clientVersion;
|
||||||
std::string otherPlayer;
|
std::string otherPlayer;
|
||||||
std::string selection;
|
std::string selection;
|
||||||
uint32_t characterId{};
|
LWOOBJID characterId{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a new bug report to the database.
|
// Add a new bug report to the database.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public:
|
|||||||
struct Info {
|
struct Info {
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string pendingName;
|
std::string pendingName;
|
||||||
uint32_t id{};
|
LWOOBJID id{};
|
||||||
uint32_t accountId{};
|
uint32_t accountId{};
|
||||||
bool needsRename{};
|
bool needsRename{};
|
||||||
LWOCLONEID cloneId{};
|
LWOCLONEID cloneId{};
|
||||||
@@ -25,25 +25,25 @@ public:
|
|||||||
virtual std::vector<std::string> GetApprovedCharacterNames() = 0;
|
virtual std::vector<std::string> GetApprovedCharacterNames() = 0;
|
||||||
|
|
||||||
// Get the character info for the given character id.
|
// Get the character info for the given character id.
|
||||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) = 0;
|
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) = 0;
|
||||||
|
|
||||||
// Get the character info for the given character name.
|
// Get the character info for the given character name.
|
||||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view name) = 0;
|
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view name) = 0;
|
||||||
|
|
||||||
// Get the character ids for the given account.
|
// Get the character ids for the given account.
|
||||||
virtual std::vector<uint32_t> GetAccountCharacterIds(const uint32_t accountId) = 0;
|
virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0;
|
||||||
|
|
||||||
// Insert a new character into the database.
|
// Insert a new character into the database.
|
||||||
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
||||||
|
|
||||||
// Set the name of the given character.
|
// Set the name of the given character.
|
||||||
virtual void SetCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
virtual void SetCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
||||||
|
|
||||||
// Set the pending name of the given character.
|
// Set the pending name of the given character.
|
||||||
virtual void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
virtual void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
||||||
|
|
||||||
// Updates the given character ids last login to be right now.
|
// Updates the given character ids last login to be right now.
|
||||||
virtual void UpdateLastLoggedInCharacter(const uint32_t characterId) = 0;
|
virtual void UpdateLastLoggedInCharacter(const LWOOBJID characterId) = 0;
|
||||||
|
|
||||||
virtual bool IsNameInUse(const std::string_view name) = 0;
|
virtual bool IsNameInUse(const std::string_view name) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
class ICharXml {
|
class ICharXml {
|
||||||
public:
|
public:
|
||||||
// Get the character xml for the given character id.
|
// Get the character xml for the given character id.
|
||||||
virtual std::string GetCharacterXml(const uint32_t charId) = 0;
|
virtual std::string GetCharacterXml(const LWOOBJID charId) = 0;
|
||||||
|
|
||||||
// Update the character xml for the given character id.
|
// Update the character xml for the given character id.
|
||||||
virtual void UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) = 0;
|
virtual void UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) = 0;
|
||||||
|
|
||||||
// Insert the character xml for the given character id.
|
// Insert the character xml for the given character id.
|
||||||
virtual void InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) = 0;
|
virtual void InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ICHARXML__H__
|
#endif //!__ICHARXML__H__
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class ICommandLog {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// Insert a new slash command log entry.
|
// Insert a new slash command log entry.
|
||||||
virtual void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) = 0;
|
virtual void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ICOMMANDLOG__H__
|
#endif //!__ICOMMANDLOG__H__
|
||||||
|
|||||||
@@ -8,25 +8,25 @@
|
|||||||
class IFriends {
|
class IFriends {
|
||||||
public:
|
public:
|
||||||
struct BestFriendStatus {
|
struct BestFriendStatus {
|
||||||
uint32_t playerCharacterId{};
|
LWOOBJID playerCharacterId{};
|
||||||
uint32_t friendCharacterId{};
|
LWOOBJID friendCharacterId{};
|
||||||
uint32_t bestFriendStatus{};
|
uint32_t bestFriendStatus{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the friends list for the given character id.
|
// Get the friends list for the given character id.
|
||||||
virtual std::vector<FriendData> GetFriendsList(const uint32_t charId) = 0;
|
virtual std::vector<FriendData> GetFriendsList(const LWOOBJID charId) = 0;
|
||||||
|
|
||||||
// Get the best friend status for the given player and friend character ids.
|
// Get the best friend status for the given player and friend character ids.
|
||||||
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||||
|
|
||||||
// Set the best friend status for the given player and friend character ids.
|
// Set the best friend status for the given player and friend character ids.
|
||||||
virtual void SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
virtual void SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
||||||
|
|
||||||
// Add a friend to the given character id.
|
// Add a friend to the given character id.
|
||||||
virtual void AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
virtual void AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||||
|
|
||||||
// Remove a friend from the given character id.
|
// Remove a friend from the given character id.
|
||||||
virtual void RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
virtual void RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IFRIENDS__H__
|
#endif //!__IFRIENDS__H__
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ class IIgnoreList {
|
|||||||
public:
|
public:
|
||||||
struct Info {
|
struct Info {
|
||||||
std::string name;
|
std::string name;
|
||||||
uint32_t id;
|
LWOOBJID id;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual std::vector<Info> GetIgnoreList(const uint32_t playerId) = 0;
|
virtual std::vector<Info> GetIgnoreList(const LWOOBJID playerId) = 0;
|
||||||
virtual void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
virtual void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
||||||
virtual void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
virtual void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IIGNORELIST__H__
|
#endif //!__IIGNORELIST__H__
|
||||||
|
|||||||
@@ -5,12 +5,13 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
class ILeaderboard {
|
class ILeaderboard {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
uint32_t charId{};
|
LWOOBJID charId{};
|
||||||
uint32_t lastPlayedTimestamp{};
|
uint32_t lastPlayedTimestamp{};
|
||||||
float primaryScore{};
|
float primaryScore{};
|
||||||
float secondaryScore{};
|
float secondaryScore{};
|
||||||
@@ -36,12 +37,12 @@ public:
|
|||||||
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
virtual std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
||||||
virtual std::optional<Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) = 0;
|
virtual std::optional<Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
||||||
|
|
||||||
virtual void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
virtual void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) = 0;
|
||||||
virtual void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
virtual void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) = 0;
|
||||||
virtual void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) = 0;
|
virtual void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
||||||
virtual void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) = 0;
|
virtual void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ILEADERBOARD__H__
|
#endif //!__ILEADERBOARD__H__
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ public:
|
|||||||
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
||||||
|
|
||||||
// Get the mail for the given character id.
|
// Get the mail for the given character id.
|
||||||
virtual std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) = 0;
|
virtual std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) = 0;
|
||||||
|
|
||||||
// Get the mail for the given mail id.
|
// Get the mail for the given mail id.
|
||||||
virtual std::optional<MailInfo> GetMail(const uint64_t mailId) = 0;
|
virtual std::optional<MailInfo> GetMail(const uint64_t mailId) = 0;
|
||||||
|
|
||||||
// Get the number of unread mail for the given character id.
|
// Get the number of unread mail for the given character id.
|
||||||
virtual uint32_t GetUnreadMailCount(const uint32_t characterId) = 0;
|
virtual uint32_t GetUnreadMailCount(const LWOOBJID characterId) = 0;
|
||||||
|
|
||||||
// Mark the given mail as read.
|
// Mark the given mail as read.
|
||||||
virtual void MarkMailRead(const uint64_t mailId) = 0;
|
virtual void MarkMailRead(const uint64_t mailId) = 0;
|
||||||
|
|||||||
@@ -6,14 +6,19 @@
|
|||||||
|
|
||||||
class IObjectIdTracker {
|
class IObjectIdTracker {
|
||||||
public:
|
public:
|
||||||
|
// Only the first 48 bits of the ids are the id, the last 16 bits are reserved for flags.
|
||||||
|
struct Range {
|
||||||
|
uint64_t minID{}; // Only the first 48 bits are the id, the last 16 bits are reserved for flags.
|
||||||
|
uint64_t maxID{}; // Only the first 48 bits are the id, the last 16 bits are reserved for flags.
|
||||||
|
};
|
||||||
|
|
||||||
// Get the current persistent id.
|
// Get the current persistent id.
|
||||||
virtual std::optional<uint32_t> GetCurrentPersistentId() = 0;
|
virtual std::optional<uint64_t> GetCurrentPersistentId() = 0;
|
||||||
|
|
||||||
// Insert the default persistent id.
|
// Insert the default persistent id.
|
||||||
virtual void InsertDefaultPersistentId() = 0;
|
virtual void InsertDefaultPersistentId() = 0;
|
||||||
|
|
||||||
// Update the persistent id.
|
virtual Range GetPersistentIdRange() = 0;
|
||||||
virtual void UpdatePersistentId(const uint32_t newId) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__IOBJECTIDTRACKER__H__
|
#endif //!__IOBJECTIDTRACKER__H__
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
std::string description;
|
std::string description;
|
||||||
std::string rejectionReason;
|
std::string rejectionReason;
|
||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
uint32_t ownerId{};
|
LWOOBJID ownerId{};
|
||||||
LWOCLONEID cloneId{};
|
LWOCLONEID cloneId{};
|
||||||
int32_t privacyOption{};
|
int32_t privacyOption{};
|
||||||
uint32_t modApproved{};
|
uint32_t modApproved{};
|
||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
uint32_t mapId{};
|
uint32_t mapId{};
|
||||||
std::string searchString;
|
std::string searchString;
|
||||||
ePropertySortType sortChoice{};
|
ePropertySortType sortChoice{};
|
||||||
uint32_t playerId{};
|
LWOOBJID playerId{};
|
||||||
uint32_t numResults{};
|
uint32_t numResults{};
|
||||||
uint32_t startIndex{};
|
uint32_t startIndex{};
|
||||||
uint32_t playerSort{};
|
uint32_t playerSort{};
|
||||||
@@ -39,6 +39,9 @@ public:
|
|||||||
std::vector<IProperty::Info> entries;
|
std::vector<IProperty::Info> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get the property info for the given property id.
|
||||||
|
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) = 0;
|
||||||
|
|
||||||
// Get the property info for the given property id.
|
// Get the property info for the given property id.
|
||||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -13,19 +13,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 position;
|
NiPoint3 position;
|
||||||
NiQuaternion rotation;
|
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||||
LWOOBJID id{};
|
LWOOBJID id{};
|
||||||
LOT lot{};
|
LOT lot{};
|
||||||
uint32_t ugcId{};
|
LWOOBJID ugcId{};
|
||||||
std::array<LWOOBJID, 5> behaviors{};
|
std::array<LWOOBJID, 5> behaviors{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inserts a new UGC model into the database.
|
// Inserts a new UGC model into the database.
|
||||||
virtual void InsertNewUgcModel(
|
virtual void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) = 0;
|
const LWOOBJID characterId) = 0;
|
||||||
|
|
||||||
// Get the property models for the given property id.
|
// Get the property models for the given property id.
|
||||||
virtual std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) = 0;
|
virtual std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) = 0;
|
||||||
@@ -45,6 +45,6 @@ public:
|
|||||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||||
|
|
||||||
// Gets a model by ID
|
// Gets a model by ID
|
||||||
virtual Model GetModel(const LWOOBJID modelID) = 0;
|
virtual std::optional<Model> GetModel(const LWOOBJID modelID) = 0;
|
||||||
};
|
};
|
||||||
#endif //!__IPROPERTIESCONTENTS__H__
|
#endif //!__IPROPERTIESCONTENTS__H__
|
||||||
|
|||||||
@@ -29,5 +29,7 @@ public:
|
|||||||
|
|
||||||
// Inserts a new UGC model into the database.
|
// Inserts a new UGC model into the database.
|
||||||
virtual void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) = 0;
|
virtual void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) = 0;
|
||||||
|
|
||||||
|
virtual std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) = 0;
|
||||||
};
|
};
|
||||||
#endif //!__IUGC__H__
|
#endif //!__IUGC__H__
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class IUgcModularBuild {
|
class IUgcModularBuild {
|
||||||
public:
|
public:
|
||||||
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) = 0;
|
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) = 0;
|
||||||
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ void MySQLDatabase::SetAutoCommit(bool value) {
|
|||||||
con->setAutoCommit(value);
|
con->setAutoCommit(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
void MySQLDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||||
ExecuteDelete("DELETE FROM charxml WHERE id=? LIMIT 1;", characterId);
|
ExecuteDelete("DELETE FROM charxml WHERE id=? LIMIT 1;", characterId);
|
||||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||||
|
|||||||
@@ -40,31 +40,31 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
||||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
||||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||||
void CreateMigrationHistoryTable() override;
|
void CreateMigrationHistoryTable() override;
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
bool IsMigrationRun(const std::string_view str) override;
|
||||||
void InsertMigration(const std::string_view str) override;
|
void InsertMigration(const std::string_view str) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
||||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||||
void DeleteCharacter(const uint32_t characterId) override;
|
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||||
@@ -83,30 +83,30 @@ public:
|
|||||||
void InsertNewMail(const MailInfo& mail) override;
|
void InsertNewMail(const MailInfo& mail) override;
|
||||||
void InsertNewUgcModel(
|
void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) override;
|
const LWOOBJID characterId) override;
|
||||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
||||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
void MarkMailRead(const uint64_t mailId) override;
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
void DeleteMail(const uint64_t mailId) override;
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
void ClaimMailItem(const uint64_t mailId) override;
|
||||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint64_t> GetCurrentPersistentId() override;
|
||||||
|
IObjectIdTracker::Range GetPersistentIdRange() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
void AddBehavior(const IBehaviors::Info& info) override;
|
||||||
@@ -118,16 +118,18 @@ public:
|
|||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
||||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
||||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
std::optional<ILeaderboard::Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||||
uint32_t GetAccountCount() override;
|
uint32_t GetAccountCount() override;
|
||||||
bool IsNameInUse(const std::string_view name) override;
|
bool IsNameInUse(const std::string_view name) override;
|
||||||
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
||||||
|
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
||||||
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
||||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -168,91 +170,91 @@ private:
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
|
||||||
// LOG("%s", param.data());
|
LOG_DEBUG("%s", param.data());
|
||||||
stmt->setString(index, param.data());
|
stmt->setString(index, param.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
|
||||||
// LOG("%s", param);
|
LOG_DEBUG("%s", param);
|
||||||
stmt->setString(index, param);
|
stmt->setString(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
|
||||||
// LOG("%s", param.c_str());
|
LOG_DEBUG("%s", param.c_str());
|
||||||
stmt->setString(index, param.c_str());
|
stmt->setString(index, param.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
|
||||||
// LOG("%u", param);
|
LOG_DEBUG("%u", param);
|
||||||
stmt->setByte(index, param);
|
stmt->setByte(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
|
||||||
// LOG("%d", param);
|
LOG_DEBUG("%d", param);
|
||||||
stmt->setByte(index, param);
|
stmt->setByte(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
|
||||||
// LOG("%u", param);
|
LOG_DEBUG("%u", param);
|
||||||
stmt->setShort(index, param);
|
stmt->setShort(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
|
||||||
// LOG("%d", param);
|
LOG_DEBUG("%d", param);
|
||||||
stmt->setShort(index, param);
|
stmt->setShort(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
|
||||||
// LOG("%u", param);
|
LOG_DEBUG("%u", param);
|
||||||
stmt->setUInt(index, param);
|
stmt->setUInt(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
|
||||||
// LOG("%d", param);
|
LOG_DEBUG("%d", param);
|
||||||
stmt->setInt(index, param);
|
stmt->setInt(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
|
||||||
// LOG("%llu", param);
|
LOG_DEBUG("%llu", param);
|
||||||
stmt->setInt64(index, param);
|
stmt->setInt64(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
|
||||||
// LOG("%llu", param);
|
LOG_DEBUG("%llu", param);
|
||||||
stmt->setUInt64(index, param);
|
stmt->setUInt64(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
|
||||||
// LOG("%f", param);
|
LOG_DEBUG("%f", param);
|
||||||
stmt->setFloat(index, param);
|
stmt->setFloat(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
|
||||||
// LOG("%f", param);
|
LOG_DEBUG("%f", param);
|
||||||
stmt->setDouble(index, param);
|
stmt->setDouble(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
|
||||||
// LOG("%d", param);
|
LOG_DEBUG("%s", param ? "true" : "false");
|
||||||
stmt->setBoolean(index, param);
|
stmt->setBoolean(index, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
|
||||||
// LOG("Blob");
|
LOG_DEBUG("Blob");
|
||||||
// This is the one time you will ever see me use const_cast.
|
// This is the one time you will ever see me use const_cast.
|
||||||
stmt->setBlob(index, const_cast<std::istream*>(param));
|
stmt->setBlob(index, const_cast<std::istream*>(param));
|
||||||
}
|
}
|
||||||
@@ -260,10 +262,21 @@ inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istr
|
|||||||
template<>
|
template<>
|
||||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
||||||
if (param) {
|
if (param) {
|
||||||
// LOG("%d", param.value());
|
LOG_DEBUG("%d", param.value());
|
||||||
stmt->setInt(index, param.value());
|
stmt->setInt(index, param.value());
|
||||||
} else {
|
} else {
|
||||||
// LOG("Null");
|
LOG_DEBUG("Null");
|
||||||
|
stmt->setNull(index, sql::DataType::SQLNULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<LWOOBJID> param) {
|
||||||
|
if (param) {
|
||||||
|
LOG_DEBUG("%d", param.value());
|
||||||
|
stmt->setInt64(index, param.value());
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("Null");
|
||||||
stmt->setNull(index, sql::DataType::SQLNULL);
|
stmt->setNull(index, sql::DataType::SQLNULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_view username) {
|
std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_view username) {
|
||||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level FROM accounts WHERE name = ? LIMIT 1;", username);
|
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level, mute_expire FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||||
|
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -16,6 +16,7 @@ std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_v
|
|||||||
toReturn.banned = result->getBoolean("banned");
|
toReturn.banned = result->getBoolean("banned");
|
||||||
toReturn.locked = result->getBoolean("locked");
|
toReturn.locked = result->getBoolean("locked");
|
||||||
toReturn.playKeyId = result->getUInt("play_key_id");
|
toReturn.playKeyId = result->getUInt("play_key_id");
|
||||||
|
toReturn.muteExpire = result->getUInt64("mute_expire");
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
void MySQLDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
||||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(std::unique_ptr<sql::Resu
|
|||||||
|
|
||||||
ICharInfo::Info toReturn;
|
ICharInfo::Info toReturn;
|
||||||
|
|
||||||
toReturn.id = stmt->getUInt("id");
|
toReturn.id = stmt->getInt64("id");
|
||||||
toReturn.name = stmt->getString("name").c_str();
|
toReturn.name = stmt->getString("name").c_str();
|
||||||
toReturn.pendingName = stmt->getString("pending_name").c_str();
|
toReturn.pendingName = stmt->getString("pending_name").c_str();
|
||||||
toReturn.needsRename = stmt->getBoolean("needs_rename");
|
toReturn.needsRename = stmt->getBoolean("needs_rename");
|
||||||
@@ -30,7 +30,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(std::unique_ptr<sql::Resu
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
||||||
return CharInfoFromQueryResult(
|
return CharInfoFromQueryResult(
|
||||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId)
|
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId)
|
||||||
);
|
);
|
||||||
@@ -42,13 +42,13 @@ std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const std::string
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> MySQLDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
std::vector<LWOOBJID> MySQLDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
||||||
auto result = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
auto result = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||||
|
|
||||||
std::vector<uint32_t> toReturn;
|
std::vector<LWOOBJID> toReturn;
|
||||||
toReturn.reserve(result->rowsCount());
|
toReturn.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
toReturn.push_back(result->getUInt("id"));
|
toReturn.push_back(result->getInt64("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -65,15 +65,15 @@ void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|||||||
static_cast<uint32_t>(time(NULL)));
|
static_cast<uint32_t>(time(NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
void MySQLDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
void MySQLDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
void MySQLDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ? LIMIT 1", static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ? LIMIT 1", static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::string MySQLDatabase::GetCharacterXml(const uint32_t charId) {
|
std::string MySQLDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||||
auto result = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
auto result = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||||
|
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
@@ -10,10 +10,10 @@ std::string MySQLDatabase::GetCharacterXml(const uint32_t charId) {
|
|||||||
return result->getString("xml_data").c_str();
|
return result->getString("xml_data").c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
void MySQLDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
||||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
void MySQLDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
void MySQLDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::vector<FriendData> MySQLDatabase::GetFriendsList(const uint32_t charId) {
|
std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||||
auto friendsList = ExecuteSelect(
|
auto friendsList = ExecuteSelect(
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
||||||
@@ -19,7 +19,7 @@ std::vector<FriendData> MySQLDatabase::GetFriendsList(const uint32_t charId) {
|
|||||||
|
|
||||||
while (friendsList->next()) {
|
while (friendsList->next()) {
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.friendID = friendsList->getUInt("player");
|
fd.friendID = friendsList->getUInt64("player");
|
||||||
fd.isBestFriend = friendsList->getInt("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendsList->getInt("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
fd.friendName = friendsList->getString("name").c_str();
|
fd.friendName = friendsList->getString("name").c_str();
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ std::vector<FriendData> MySQLDatabase::GetFriendsList(const uint32_t charId) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
auto result = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
auto result = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
@@ -42,14 +42,14 @@ std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(con
|
|||||||
}
|
}
|
||||||
|
|
||||||
IFriends::BestFriendStatus toReturn;
|
IFriends::BestFriendStatus toReturn;
|
||||||
toReturn.playerCharacterId = result->getUInt("player_id");
|
toReturn.playerCharacterId = result->getUInt64("player_id");
|
||||||
toReturn.friendCharacterId = result->getUInt("friend_id");
|
toReturn.friendCharacterId = result->getUInt64("friend_id");
|
||||||
toReturn.bestFriendStatus = result->getUInt("best_friend");
|
toReturn.bestFriendStatus = result->getUInt("best_friend");
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
void MySQLDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) {
|
||||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
bestFriendStatus,
|
bestFriendStatus,
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
@@ -59,11 +59,11 @@ void MySQLDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
void MySQLDatabase::AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
ExecuteInsert("INSERT IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
ExecuteInsert("INSERT IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
void MySQLDatabase::RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||||
auto result = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
auto result = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> ignoreList;
|
std::vector<IIgnoreList::Info> ignoreList;
|
||||||
|
|
||||||
ignoreList.reserve(result->rowsCount());
|
ignoreList.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getUInt("ignore_id") });
|
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getInt64("ignore_id") });
|
||||||
}
|
}
|
||||||
|
|
||||||
return ignoreList;
|
return ignoreList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void MySQLDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void MySQLDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ std::vector<ILeaderboard::Entry> ProcessQuery(UniqueResultSet& rows) {
|
|||||||
while (rows->next()) {
|
while (rows->next()) {
|
||||||
auto& entry = entries.emplace_back();
|
auto& entry = entries.emplace_back();
|
||||||
|
|
||||||
entry.charId = rows->getUInt("character_id");
|
entry.charId = rows->getUInt64("character_id");
|
||||||
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
||||||
entry.primaryScore = rows->getFloat("primaryScore");
|
entry.primaryScore = rows->getFloat("primaryScore");
|
||||||
entry.secondaryScore = rows->getFloat("secondaryScore");
|
entry.secondaryScore = rows->getFloat("secondaryScore");
|
||||||
@@ -58,21 +58,21 @@ std::vector<ILeaderboard::Entry> MySQLDatabase::GetNsLeaderboard(const uint32_t
|
|||||||
return ProcessQuery(leaderboard);
|
return ProcessQuery(leaderboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
void MySQLDatabase::SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
void MySQLDatabase::UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
void MySQLDatabase::IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||||
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
if (res->next()) {
|
if (res->next()) {
|
||||||
@@ -86,6 +86,6 @@ std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
void MySQLDatabase::IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void MySQLDatabase::InsertNewMail(const MailInfo& mail) {
|
|||||||
mail.itemCount);
|
mail.itemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||||
auto res = ExecuteSelect(
|
auto res = ExecuteSelect(
|
||||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||||
" FROM mail WHERE receiver_id=? limit ?;",
|
" FROM mail WHERE receiver_id=? limit ?;",
|
||||||
@@ -61,7 +61,7 @@ std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
uint32_t MySQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||||
auto res = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
auto res = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||||
|
|
||||||
if (!res->next()) {
|
if (!res->next()) {
|
||||||
|
|||||||
@@ -1,17 +1,42 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
std::optional<uint32_t> MySQLDatabase::GetCurrentPersistentId() {
|
std::optional<uint64_t> MySQLDatabase::GetCurrentPersistentId() {
|
||||||
auto result = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
auto result = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return result->getUInt("last_object_id");
|
return result->getUInt64("last_object_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertDefaultPersistentId() {
|
void MySQLDatabase::InsertDefaultPersistentId() {
|
||||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdatePersistentId(const uint32_t newId) {
|
IObjectIdTracker::Range MySQLDatabase::GetPersistentIdRange() {
|
||||||
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
IObjectIdTracker::Range range;
|
||||||
|
auto prevCommit = GetAutoCommit();
|
||||||
|
SetAutoCommit(false);
|
||||||
|
|
||||||
|
// THIS MUST ABSOLUTELY NOT FAIL. These IDs are expected to be unique. As such a transactional select is used to safely get a range
|
||||||
|
// of IDs that will never be used again. A separate feature could track unused IDs and recycle them, but that is not implemented.
|
||||||
|
ExecuteCustomQuery("START TRANSACTION;");
|
||||||
|
// 200 seems like a good range to reserve at once. Only way this would be noticable is if a player
|
||||||
|
// added hundreds of items at once.
|
||||||
|
// Doing the update first ensures that all other connections are blocked from accessing this table until we commit.
|
||||||
|
auto result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
||||||
|
// If no rows were updated, it means the table is empty, so we need to insert the default row first.
|
||||||
|
if (result == 0) {
|
||||||
|
InsertDefaultPersistentId();
|
||||||
|
result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point all connections are waiting on us to finish the transaction, so we can safely select the ID we just set.
|
||||||
|
auto selectRes = ExecuteSelect("SELECT last_object_id FROM object_id_tracker;");
|
||||||
|
selectRes->next();
|
||||||
|
range.maxID = selectRes->getUInt64("last_object_id");
|
||||||
|
range.minID = range.maxID - 199;
|
||||||
|
|
||||||
|
ExecuteCustomQuery("COMMIT;");
|
||||||
|
SetAutoCommit(prevCommit);
|
||||||
|
return range;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,23 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
#include "ePropertySortType.h"
|
#include "ePropertySortType.h"
|
||||||
|
|
||||||
|
IProperty::Info ReadPropertyInfo(UniqueResultSet& result) {
|
||||||
|
IProperty::Info info;
|
||||||
|
info.id = result->getUInt64("id");
|
||||||
|
info.ownerId = result->getInt64("owner_id");
|
||||||
|
info.cloneId = result->getUInt64("clone_id");
|
||||||
|
info.name = result->getString("name").c_str();
|
||||||
|
info.description = result->getString("description").c_str();
|
||||||
|
info.privacyOption = result->getInt("privacy_option");
|
||||||
|
info.rejectionReason = result->getString("rejection_reason").c_str();
|
||||||
|
info.lastUpdatedTime = result->getUInt("last_updated");
|
||||||
|
info.claimedTime = result->getUInt("time_claimed");
|
||||||
|
info.reputation = result->getUInt("reputation");
|
||||||
|
info.modApproved = result->getUInt("mod_approved");
|
||||||
|
info.performanceCost = result->getFloat("performance_cost");
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||||
std::optional<IProperty::PropertyEntranceResult> result;
|
std::optional<IProperty::PropertyEntranceResult> result;
|
||||||
std::string query;
|
std::string query;
|
||||||
@@ -117,19 +134,7 @@ std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(co
|
|||||||
|
|
||||||
while (properties->next()) {
|
while (properties->next()) {
|
||||||
if (!result) result = IProperty::PropertyEntranceResult();
|
if (!result) result = IProperty::PropertyEntranceResult();
|
||||||
auto& entry = result->entries.emplace_back();
|
result->entries.push_back(ReadPropertyInfo(properties));
|
||||||
entry.id = properties->getUInt64("id");
|
|
||||||
entry.ownerId = properties->getUInt64("owner_id");
|
|
||||||
entry.cloneId = properties->getUInt64("clone_id");
|
|
||||||
entry.name = properties->getString("name").c_str();
|
|
||||||
entry.description = properties->getString("description").c_str();
|
|
||||||
entry.privacyOption = properties->getInt("privacy_option");
|
|
||||||
entry.rejectionReason = properties->getString("rejection_reason").c_str();
|
|
||||||
entry.lastUpdatedTime = properties->getUInt("last_updated");
|
|
||||||
entry.claimedTime = properties->getUInt("time_claimed");
|
|
||||||
entry.reputation = properties->getUInt("reputation");
|
|
||||||
entry.modApproved = properties->getUInt("mod_approved");
|
|
||||||
entry.performanceCost = properties->getFloat("performance_cost");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -144,21 +149,7 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
IProperty::Info toReturn;
|
return ReadPropertyInfo(propertyEntry);
|
||||||
toReturn.id = propertyEntry->getUInt64("id");
|
|
||||||
toReturn.ownerId = propertyEntry->getUInt64("owner_id");
|
|
||||||
toReturn.cloneId = propertyEntry->getUInt64("clone_id");
|
|
||||||
toReturn.name = propertyEntry->getString("name").c_str();
|
|
||||||
toReturn.description = propertyEntry->getString("description").c_str();
|
|
||||||
toReturn.privacyOption = propertyEntry->getInt("privacy_option");
|
|
||||||
toReturn.rejectionReason = propertyEntry->getString("rejection_reason").c_str();
|
|
||||||
toReturn.lastUpdatedTime = propertyEntry->getUInt("last_updated");
|
|
||||||
toReturn.claimedTime = propertyEntry->getUInt("time_claimed");
|
|
||||||
toReturn.reputation = propertyEntry->getUInt("reputation");
|
|
||||||
toReturn.modApproved = propertyEntry->getUInt("mod_approved");
|
|
||||||
toReturn.performanceCost = propertyEntry->getFloat("performance_cost");
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
void MySQLDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||||
@@ -195,3 +186,15 @@ void MySQLDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_
|
|||||||
zoneId.GetMapID()
|
zoneId.GetMapID()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOOBJID id) {
|
||||||
|
auto propertyEntry = ExecuteSelect(
|
||||||
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||||
|
"FROM properties WHERE id = ?;", id);
|
||||||
|
|
||||||
|
if (!propertyEntry->next()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReadPropertyInfo(propertyEntry);
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,26 +64,27 @@ void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
|||||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyContents::Model MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
std::optional<IPropertyContents::Model> MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
||||||
auto result = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
auto result = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
||||||
|
|
||||||
IPropertyContents::Model model{};
|
std::optional<IPropertyContents::Model> model = std::nullopt;
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
model.id = result->getUInt64("id");
|
model = IPropertyContents::Model{};
|
||||||
model.lot = static_cast<LOT>(result->getUInt("lot"));
|
model->id = result->getUInt64("id");
|
||||||
model.position.x = result->getFloat("x");
|
model->lot = static_cast<LOT>(result->getUInt("lot"));
|
||||||
model.position.y = result->getFloat("y");
|
model->position.x = result->getFloat("x");
|
||||||
model.position.z = result->getFloat("z");
|
model->position.y = result->getFloat("y");
|
||||||
model.rotation.w = result->getFloat("rw");
|
model->position.z = result->getFloat("z");
|
||||||
model.rotation.x = result->getFloat("rx");
|
model->rotation.w = result->getFloat("rw");
|
||||||
model.rotation.y = result->getFloat("ry");
|
model->rotation.x = result->getFloat("rx");
|
||||||
model.rotation.z = result->getFloat("rz");
|
model->rotation.y = result->getFloat("ry");
|
||||||
model.ugcId = result->getUInt64("ugc_id");
|
model->rotation.z = result->getFloat("rz");
|
||||||
model.behaviors[0] = result->getUInt64("behavior_1");
|
model->ugcId = result->getUInt64("ugc_id");
|
||||||
model.behaviors[1] = result->getUInt64("behavior_2");
|
model->behaviors[0] = result->getUInt64("behavior_1");
|
||||||
model.behaviors[2] = result->getUInt64("behavior_3");
|
model->behaviors[1] = result->getUInt64("behavior_2");
|
||||||
model.behaviors[3] = result->getUInt64("behavior_4");
|
model->behaviors[2] = result->getUInt64("behavior_3");
|
||||||
model.behaviors[4] = result->getUInt64("behavior_5");
|
model->behaviors[3] = result->getUInt64("behavior_4");
|
||||||
|
model->behaviors[4] = result->getUInt64("behavior_5");
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
|
IUgc::Model ReadModel(UniqueResultSet& result) {
|
||||||
|
IUgc::Model model;
|
||||||
|
|
||||||
|
// blob is owned by the query, so we need to do a deep copy :/
|
||||||
|
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
||||||
|
model.lxfmlData << blob->rdbuf();
|
||||||
|
model.id = result->getUInt64("ugcID");
|
||||||
|
model.modelID = result->getUInt64("modelID");
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||||
auto result = ExecuteSelect(
|
auto result = ExecuteSelect(
|
||||||
"SELECT lxfml, u.id as ugcID, pc.id as modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
"SELECT lxfml, u.id as ugcID, pc.id as modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
||||||
@@ -8,14 +20,7 @@ std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId)
|
|||||||
std::vector<IUgc::Model> toReturn;
|
std::vector<IUgc::Model> toReturn;
|
||||||
|
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
IUgc::Model model;
|
toReturn.push_back(ReadModel(result));
|
||||||
|
|
||||||
// blob is owned by the query, so we need to do a deep copy :/
|
|
||||||
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
|
||||||
model.lxfmlData << blob->rdbuf();
|
|
||||||
model.id = result->getUInt64("ugcID");
|
|
||||||
model.modelID = result->getUInt64("modelID");
|
|
||||||
toReturn.push_back(std::move(model));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -27,14 +32,7 @@ std::vector<IUgc::Model> MySQLDatabase::GetAllUgcModels() {
|
|||||||
std::vector<IUgc::Model> models;
|
std::vector<IUgc::Model> models;
|
||||||
models.reserve(result->rowsCount());
|
models.reserve(result->rowsCount());
|
||||||
while (result->next()) {
|
while (result->next()) {
|
||||||
IUgc::Model model;
|
models.push_back(ReadModel(result));
|
||||||
model.id = result->getInt64("ugcID");
|
|
||||||
model.modelID = result->getUInt64("modelID");
|
|
||||||
|
|
||||||
// blob is owned by the query, so we need to do a deep copy :/
|
|
||||||
std::unique_ptr<std::istream> blob(result->getBlob("lxfml"));
|
|
||||||
model.lxfmlData << blob->rdbuf();
|
|
||||||
models.push_back(std::move(model));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return models;
|
return models;
|
||||||
@@ -45,10 +43,10 @@ void MySQLDatabase::RemoveUnreferencedUgcModels() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MySQLDatabase::InsertNewUgcModel(
|
void MySQLDatabase::InsertNewUgcModel(
|
||||||
std:: stringstream& sd0Data, // cant be const sad
|
std::stringstream& sd0Data, // cant be const sad
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) {
|
const LWOOBJID characterId) {
|
||||||
const std::istream stream(sd0Data.rdbuf());
|
const std::istream stream(sd0Data.rdbuf());
|
||||||
ExecuteInsert(
|
ExecuteInsert(
|
||||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||||
@@ -71,3 +69,14 @@ void MySQLDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::stringstrea
|
|||||||
const std::istream stream(lxfml.rdbuf());
|
const std::istream stream(lxfml.rdbuf());
|
||||||
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<IUgc::Model> MySQLDatabase::GetUgcModel(const LWOOBJID ugcId) {
|
||||||
|
auto result = ExecuteSelect("SELECT u.id AS ugcID, lxfml, pc.id AS modelID FROM ugc AS u JOIN properties_contents AS pc ON pc.ugc_id = u.id WHERE u.id = ?", ugcId);
|
||||||
|
|
||||||
|
std::optional<IUgc::Model> toReturn = std::nullopt;
|
||||||
|
if (result->next()) {
|
||||||
|
toReturn = ReadModel(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
|
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) {
|
||||||
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,13 +61,13 @@ bool SQLiteDatabase::GetAutoCommit() {
|
|||||||
|
|
||||||
void SQLiteDatabase::SetAutoCommit(bool value) {
|
void SQLiteDatabase::SetAutoCommit(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
|
||||||
} else {
|
|
||||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
||||||
|
} else {
|
||||||
|
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::DeleteCharacter(const uint32_t characterId) {
|
void SQLiteDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||||
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||||
|
|||||||
@@ -38,31 +38,31 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
||||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
||||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||||
void CreateMigrationHistoryTable() override;
|
void CreateMigrationHistoryTable() override;
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
bool IsMigrationRun(const std::string_view str) override;
|
||||||
void InsertMigration(const std::string_view str) override;
|
void InsertMigration(const std::string_view str) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
||||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||||
void DeleteCharacter(const uint32_t characterId) override;
|
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||||
@@ -81,30 +81,30 @@ public:
|
|||||||
void InsertNewMail(const MailInfo& mail) override;
|
void InsertNewMail(const MailInfo& mail) override;
|
||||||
void InsertNewUgcModel(
|
void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) override;
|
const LWOOBJID characterId) override;
|
||||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
||||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
void MarkMailRead(const uint64_t mailId) override;
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
void DeleteMail(const uint64_t mailId) override;
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
void ClaimMailItem(const uint64_t mailId) override;
|
||||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint64_t> GetCurrentPersistentId() override;
|
||||||
|
IObjectIdTracker::Range GetPersistentIdRange() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
void AddBehavior(const IBehaviors::Info& info) override;
|
||||||
@@ -116,16 +116,18 @@ public:
|
|||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override;
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override;
|
||||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
||||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override;
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
std::optional<ILeaderboard::Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) override;
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||||
uint32_t GetAccountCount() override;
|
uint32_t GetAccountCount() override;
|
||||||
bool IsNameInUse(const std::string_view name) override;
|
bool IsNameInUse(const std::string_view name) override;
|
||||||
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override;
|
||||||
|
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override;
|
||||||
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override;
|
||||||
private:
|
private:
|
||||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
||||||
|
|
||||||
@@ -270,4 +272,15 @@ inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<u
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void SetParam(PreppedStmtRef stmt, const int index, const std::optional<LWOOBJID> param) {
|
||||||
|
if (param) {
|
||||||
|
LOG("%d", param.value());
|
||||||
|
stmt.bind(index, static_cast<sqlite_int64>(param.value()));
|
||||||
|
} else {
|
||||||
|
LOG("Null");
|
||||||
|
stmt.bindNull(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif //!SQLITEDATABASE_H
|
#endif //!SQLITEDATABASE_H
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_
|
|||||||
toReturn.banned = result.getIntField("banned");
|
toReturn.banned = result.getIntField("banned");
|
||||||
toReturn.locked = result.getIntField("locked");
|
toReturn.locked = result.getIntField("locked");
|
||||||
toReturn.playKeyId = result.getIntField("play_key_id");
|
toReturn.playKeyId = result.getIntField("play_key_id");
|
||||||
|
toReturn.muteExpire = static_cast<uint64_t>(result.getInt64Field("mute_expire"));
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
void SQLiteDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
ExecuteInsert("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);",
|
||||||
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
characterId, static_cast<uint32_t>(activityType), static_cast<uint32_t>(time(NULL)), mapId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
|||||||
|
|
||||||
ICharInfo::Info toReturn;
|
ICharInfo::Info toReturn;
|
||||||
|
|
||||||
toReturn.id = stmt.getIntField("id");
|
toReturn.id = stmt.getInt64Field("id");
|
||||||
toReturn.name = stmt.getStringField("name");
|
toReturn.name = stmt.getStringField("name");
|
||||||
toReturn.pendingName = stmt.getStringField("pending_name");
|
toReturn.pendingName = stmt.getStringField("pending_name");
|
||||||
toReturn.needsRename = stmt.getIntField("needs_rename");
|
toReturn.needsRename = stmt.getIntField("needs_rename");
|
||||||
@@ -31,7 +31,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const uint32_t charId) {
|
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
||||||
return CharInfoFromQueryResult(
|
return CharInfoFromQueryResult(
|
||||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId).second
|
||||||
);
|
);
|
||||||
@@ -43,12 +43,12 @@ std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const std::strin
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> SQLiteDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
std::vector<LWOOBJID> SQLiteDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||||
|
|
||||||
std::vector<uint32_t> toReturn;
|
std::vector<LWOOBJID> toReturn;
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
toReturn.push_back(result.getIntField("id"));
|
toReturn.push_back(result.getInt64Field("id"));
|
||||||
result.nextRow();
|
result.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,15 +66,15 @@ void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|||||||
static_cast<uint32_t>(time(NULL)));
|
static_cast<uint32_t>(time(NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
void SQLiteDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
void SQLiteDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET pending_name = ?, needs_rename = 0, last_login = ? WHERE id = ?;", name, static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
void SQLiteDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
std::string SQLiteDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||||
|
|
||||||
if (result.eof()) {
|
if (result.eof()) {
|
||||||
@@ -10,10 +10,10 @@ std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
|||||||
return result.getStringField("xml_data");
|
return result.getStringField("xml_data");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
void SQLiteDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
||||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
void SQLiteDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
void SQLiteDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||||
auto [_, friendsList] = ExecuteSelect(
|
auto [_, friendsList] = ExecuteSelect(
|
||||||
R"QUERY(
|
R"QUERY(
|
||||||
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
SELECT fr.requested_player AS player, best_friend AS bff, ci.name AS name FROM
|
||||||
@@ -18,7 +18,7 @@ std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
|||||||
|
|
||||||
while (!friendsList.eof()) {
|
while (!friendsList.eof()) {
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.friendID = friendsList.getIntField("player");
|
fd.friendID = friendsList.getInt64Field("player");
|
||||||
fd.isBestFriend = friendsList.getIntField("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendsList.getIntField("bff") == 3; // 0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
fd.friendName = friendsList.getStringField("name");
|
fd.friendName = friendsList.getStringField("name");
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
auto [_, result] = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
@@ -42,14 +42,14 @@ std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(co
|
|||||||
}
|
}
|
||||||
|
|
||||||
IFriends::BestFriendStatus toReturn;
|
IFriends::BestFriendStatus toReturn;
|
||||||
toReturn.playerCharacterId = result.getIntField("player_id");
|
toReturn.playerCharacterId = result.getInt64Field("player_id");
|
||||||
toReturn.friendCharacterId = result.getIntField("friend_id");
|
toReturn.friendCharacterId = result.getInt64Field("friend_id");
|
||||||
toReturn.bestFriendStatus = result.getIntField("best_friend");
|
toReturn.bestFriendStatus = result.getIntField("best_friend");
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
void SQLiteDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) {
|
||||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||||
bestFriendStatus,
|
bestFriendStatus,
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
@@ -59,11 +59,11 @@ void SQLiteDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
void SQLiteDatabase::AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
ExecuteInsert("INSERT OR IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
ExecuteInsert("INSERT OR IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
void SQLiteDatabase::RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||||
playerCharacterId,
|
playerCharacterId,
|
||||||
friendCharacterId,
|
friendCharacterId,
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const uint32_t playerId) {
|
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
auto [_, result] = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> ignoreList;
|
std::vector<IIgnoreList::Info> ignoreList;
|
||||||
|
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), static_cast<uint32_t>(result.getIntField("ignore_id")) });
|
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), result.getInt64Field("ignore_id") });
|
||||||
result.nextRow();
|
result.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ignoreList;
|
return ignoreList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void SQLiteDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
ExecuteInsert("INSERT OR IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
ExecuteInsert("INSERT OR IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void SQLiteDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ std::vector<ILeaderboard::Entry> ProcessQuery(CppSQLite3Query& rows) {
|
|||||||
while (!rows.eof()) {
|
while (!rows.eof()) {
|
||||||
auto& entry = entries.emplace_back();
|
auto& entry = entries.emplace_back();
|
||||||
|
|
||||||
entry.charId = rows.getIntField("character_id");
|
entry.charId = rows.getInt64Field("character_id");
|
||||||
entry.lastPlayedTimestamp = rows.getIntField("lp_unix");
|
entry.lastPlayedTimestamp = rows.getIntField("lp_unix");
|
||||||
entry.primaryScore = rows.getFloatField("primaryScore");
|
entry.primaryScore = rows.getFloatField("primaryScore");
|
||||||
entry.secondaryScore = rows.getFloatField("secondaryScore");
|
entry.secondaryScore = rows.getFloatField("secondaryScore");
|
||||||
@@ -58,17 +58,17 @@ std::vector<ILeaderboard::Entry> SQLiteDatabase::GetNsLeaderboard(const uint32_t
|
|||||||
return ProcessQuery(result);
|
return ProcessQuery(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
void SQLiteDatabase::SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("INSERT INTO leaderboard (primaryScore, secondaryScore, tertiaryScore, character_id, game_id, last_played) VALUES (?,?,?,?,?,CURRENT_TIMESTAMP) ;",
|
ExecuteInsert("INSERT INTO leaderboard (primaryScore, secondaryScore, tertiaryScore, character_id, game_id, last_played) VALUES (?,?,?,?,?,CURRENT_TIMESTAMP) ;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
void SQLiteDatabase::UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;",
|
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;",
|
||||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||||
auto [_, res] = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
auto [_, res] = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
if (!res.eof()) {
|
if (!res.eof()) {
|
||||||
@@ -82,10 +82,10 @@ std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const uint32_t
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
void SQLiteDatabase::IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
void SQLiteDatabase::IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) {
|
||||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ void SQLiteDatabase::InsertNewMail(const MailInfo& mail) {
|
|||||||
mail.itemCount);
|
mail.itemCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||||
auto [_, res] = ExecuteSelect(
|
auto [_, res] = ExecuteSelect(
|
||||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||||
" FROM mail WHERE receiver_id=? limit ?;",
|
" FROM mail WHERE receiver_id=? limit ?;",
|
||||||
@@ -60,7 +60,7 @@ std::optional<MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SQLiteDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
uint32_t SQLiteDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||||
|
|
||||||
if (res.eof()) {
|
if (res.eof()) {
|
||||||
|
|||||||
@@ -1,17 +1,40 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
std::optional<uint32_t> SQLiteDatabase::GetCurrentPersistentId() {
|
std::optional<uint64_t> SQLiteDatabase::GetCurrentPersistentId() {
|
||||||
auto [_, result] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
auto [_, result] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||||
if (result.eof()) {
|
if (result.eof()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return result.getIntField("last_object_id");
|
return result.getInt64Field("last_object_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::InsertDefaultPersistentId() {
|
void SQLiteDatabase::InsertDefaultPersistentId() {
|
||||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdatePersistentId(const uint32_t newId) {
|
IObjectIdTracker::Range SQLiteDatabase::GetPersistentIdRange() {
|
||||||
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
IObjectIdTracker::Range range;
|
||||||
|
auto prevCommit = GetAutoCommit();
|
||||||
|
SetAutoCommit(false); // This begins the transaction for us if one is not already in progress
|
||||||
|
|
||||||
|
// THIS MUST ABSOLUTELY NOT FAIL. These IDs are expected to be unique. As such a transactional select is used to safely get a range
|
||||||
|
// of IDs that will never be used again. A separate feature could track unused IDs and recycle them, but that is not implemented.
|
||||||
|
// 200 seems like a good range to reserve at once. Only way this would be noticable is if a player
|
||||||
|
// added hundreds of items at once.
|
||||||
|
// Doing the update first ensures that all other connections are blocked from accessing this table until we commit.
|
||||||
|
auto result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
||||||
|
if (result == 0) {
|
||||||
|
InsertDefaultPersistentId();
|
||||||
|
result = ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = last_object_id + 200;");
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point all connections are waiting on us to finish the transaction, so we can safely select the ID we just set.
|
||||||
|
auto [_, selectResult] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker;");
|
||||||
|
range.maxID = selectResult.getInt64Field("last_object_id");
|
||||||
|
range.minID = range.maxID - 199;
|
||||||
|
|
||||||
|
// We must commit here manually, this will unlock the database for all other servers
|
||||||
|
ExecuteCustomQuery("COMMIT;");
|
||||||
|
SetAutoCommit(prevCommit);
|
||||||
|
return range;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,23 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
#include "ePropertySortType.h"
|
#include "ePropertySortType.h"
|
||||||
|
|
||||||
|
IProperty::Info ReadPropertyInfo(CppSQLite3Query& propertyEntry) {
|
||||||
|
IProperty::Info toReturn;
|
||||||
|
toReturn.id = propertyEntry.getInt64Field("id");
|
||||||
|
toReturn.ownerId = propertyEntry.getInt64Field("owner_id");
|
||||||
|
toReturn.cloneId = propertyEntry.getInt64Field("clone_id");
|
||||||
|
toReturn.name = propertyEntry.getStringField("name");
|
||||||
|
toReturn.description = propertyEntry.getStringField("description");
|
||||||
|
toReturn.privacyOption = propertyEntry.getIntField("privacy_option");
|
||||||
|
toReturn.rejectionReason = propertyEntry.getStringField("rejection_reason");
|
||||||
|
toReturn.lastUpdatedTime = propertyEntry.getIntField("last_updated");
|
||||||
|
toReturn.claimedTime = propertyEntry.getIntField("time_claimed");
|
||||||
|
toReturn.reputation = propertyEntry.getIntField("reputation");
|
||||||
|
toReturn.modApproved = propertyEntry.getIntField("mod_approved");
|
||||||
|
toReturn.performanceCost = propertyEntry.getFloatField("performance_cost");
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(const IProperty::PropertyLookup& params) {
|
||||||
std::optional<IProperty::PropertyEntranceResult> result;
|
std::optional<IProperty::PropertyEntranceResult> result;
|
||||||
std::string query;
|
std::string query;
|
||||||
@@ -118,19 +135,7 @@ std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(c
|
|||||||
auto& [_, properties] = propertiesRes;
|
auto& [_, properties] = propertiesRes;
|
||||||
if (!properties.eof() && !result.has_value()) result = IProperty::PropertyEntranceResult();
|
if (!properties.eof() && !result.has_value()) result = IProperty::PropertyEntranceResult();
|
||||||
while (!properties.eof()) {
|
while (!properties.eof()) {
|
||||||
auto& entry = result->entries.emplace_back();
|
result->entries.push_back(ReadPropertyInfo(properties));
|
||||||
entry.id = properties.getInt64Field("id");
|
|
||||||
entry.ownerId = properties.getInt64Field("owner_id");
|
|
||||||
entry.cloneId = properties.getInt64Field("clone_id");
|
|
||||||
entry.name = properties.getStringField("name");
|
|
||||||
entry.description = properties.getStringField("description");
|
|
||||||
entry.privacyOption = properties.getIntField("privacy_option");
|
|
||||||
entry.rejectionReason = properties.getStringField("rejection_reason");
|
|
||||||
entry.lastUpdatedTime = properties.getIntField("last_updated");
|
|
||||||
entry.claimedTime = properties.getIntField("time_claimed");
|
|
||||||
entry.reputation = properties.getIntField("reputation");
|
|
||||||
entry.modApproved = properties.getIntField("mod_approved");
|
|
||||||
entry.performanceCost = properties.getFloatField("performance_cost");
|
|
||||||
properties.nextRow();
|
properties.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,21 +151,7 @@ std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOMAPID ma
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
IProperty::Info toReturn;
|
return ReadPropertyInfo(propertyEntry);
|
||||||
toReturn.id = propertyEntry.getInt64Field("id");
|
|
||||||
toReturn.ownerId = propertyEntry.getInt64Field("owner_id");
|
|
||||||
toReturn.cloneId = propertyEntry.getInt64Field("clone_id");
|
|
||||||
toReturn.name = propertyEntry.getStringField("name");
|
|
||||||
toReturn.description = propertyEntry.getStringField("description");
|
|
||||||
toReturn.privacyOption = propertyEntry.getIntField("privacy_option");
|
|
||||||
toReturn.rejectionReason = propertyEntry.getStringField("rejection_reason");
|
|
||||||
toReturn.lastUpdatedTime = propertyEntry.getIntField("last_updated");
|
|
||||||
toReturn.claimedTime = propertyEntry.getIntField("time_claimed");
|
|
||||||
toReturn.reputation = propertyEntry.getIntField("reputation");
|
|
||||||
toReturn.modApproved = propertyEntry.getIntField("mod_approved");
|
|
||||||
toReturn.performanceCost = propertyEntry.getFloatField("performance_cost");
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SQLiteDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
void SQLiteDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||||
@@ -197,3 +188,15 @@ void SQLiteDatabase::InsertNewProperty(const IProperty::Info& info, const uint32
|
|||||||
zoneId.GetMapID()
|
zoneId.GetMapID()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOOBJID id) {
|
||||||
|
auto [_, propertyEntry] = ExecuteSelect(
|
||||||
|
"SELECT id, owner_id, clone_id, name, description, privacy_option, rejection_reason, last_updated, time_claimed, reputation, mod_approved, performance_cost "
|
||||||
|
"FROM properties WHERE id = ?;", id);
|
||||||
|
|
||||||
|
if (propertyEntry.eof()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReadPropertyInfo(propertyEntry);
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,27 +64,28 @@ void SQLiteDatabase::RemoveModel(const LWOOBJID& modelId) {
|
|||||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyContents::Model SQLiteDatabase::GetModel(const LWOOBJID modelID) {
|
std::optional<IPropertyContents::Model> SQLiteDatabase::GetModel(const LWOOBJID modelID) {
|
||||||
auto [_, result] = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
auto [_, result] = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
||||||
|
|
||||||
IPropertyContents::Model model{};
|
std::optional<IPropertyContents::Model> model = std::nullopt;
|
||||||
if (!result.eof()) {
|
if (!result.eof()) {
|
||||||
do {
|
do {
|
||||||
model.id = result.getInt64Field("id");
|
model = IPropertyContents::Model{};
|
||||||
model.lot = static_cast<LOT>(result.getIntField("lot"));
|
model->id = result.getInt64Field("id");
|
||||||
model.position.x = result.getFloatField("x");
|
model->lot = static_cast<LOT>(result.getIntField("lot"));
|
||||||
model.position.y = result.getFloatField("y");
|
model->position.x = result.getFloatField("x");
|
||||||
model.position.z = result.getFloatField("z");
|
model->position.y = result.getFloatField("y");
|
||||||
model.rotation.w = result.getFloatField("rw");
|
model->position.z = result.getFloatField("z");
|
||||||
model.rotation.x = result.getFloatField("rx");
|
model->rotation.w = result.getFloatField("rw");
|
||||||
model.rotation.y = result.getFloatField("ry");
|
model->rotation.x = result.getFloatField("rx");
|
||||||
model.rotation.z = result.getFloatField("rz");
|
model->rotation.y = result.getFloatField("ry");
|
||||||
model.ugcId = result.getInt64Field("ugc_id");
|
model->rotation.z = result.getFloatField("rz");
|
||||||
model.behaviors[0] = result.getInt64Field("behavior_1");
|
model->ugcId = result.getInt64Field("ugc_id");
|
||||||
model.behaviors[1] = result.getInt64Field("behavior_2");
|
model->behaviors[0] = result.getInt64Field("behavior_1");
|
||||||
model.behaviors[2] = result.getInt64Field("behavior_3");
|
model->behaviors[1] = result.getInt64Field("behavior_2");
|
||||||
model.behaviors[3] = result.getInt64Field("behavior_4");
|
model->behaviors[2] = result.getInt64Field("behavior_3");
|
||||||
model.behaviors[4] = result.getInt64Field("behavior_5");
|
model->behaviors[3] = result.getInt64Field("behavior_4");
|
||||||
|
model->behaviors[4] = result.getInt64Field("behavior_5");
|
||||||
} while (result.nextRow());
|
} while (result.nextRow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
|
IUgc::Model ReadModel(CppSQLite3Query& result) {
|
||||||
|
IUgc::Model model;
|
||||||
|
|
||||||
|
int blobSize{};
|
||||||
|
const auto* blob = result.getBlobField("lxfml", blobSize);
|
||||||
|
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
||||||
|
model.id = result.getInt64Field("ugcID");
|
||||||
|
model.modelID = result.getInt64Field("modelID");
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId) {
|
||||||
auto [_, result] = ExecuteSelect(
|
auto [_, result] = ExecuteSelect(
|
||||||
"SELECT lxfml, u.id AS ugcID, pc.id AS modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
"SELECT lxfml, u.id AS ugcID, pc.id AS modelID FROM ugc AS u JOIN properties_contents AS pc ON u.id = pc.ugc_id WHERE lot = 14 AND property_id = ? AND pc.ugc_id IS NOT NULL;",
|
||||||
@@ -8,14 +20,7 @@ std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId
|
|||||||
std::vector<IUgc::Model> toReturn;
|
std::vector<IUgc::Model> toReturn;
|
||||||
|
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
IUgc::Model model;
|
toReturn.push_back(ReadModel(result));
|
||||||
|
|
||||||
int blobSize{};
|
|
||||||
const auto* blob = result.getBlobField("lxfml", blobSize);
|
|
||||||
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
|
||||||
model.id = result.getInt64Field("ugcID");
|
|
||||||
model.modelID = result.getInt64Field("modelID");
|
|
||||||
toReturn.push_back(std::move(model));
|
|
||||||
result.nextRow();
|
result.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,14 +32,7 @@ std::vector<IUgc::Model> SQLiteDatabase::GetAllUgcModels() {
|
|||||||
|
|
||||||
std::vector<IUgc::Model> models;
|
std::vector<IUgc::Model> models;
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
IUgc::Model model;
|
models.push_back(ReadModel(result));
|
||||||
model.id = result.getInt64Field("ugcID");
|
|
||||||
model.modelID = result.getInt64Field("modelID");
|
|
||||||
|
|
||||||
int blobSize{};
|
|
||||||
const auto* blob = result.getBlobField("lxfml", blobSize);
|
|
||||||
model.lxfmlData << std::string(reinterpret_cast<const char*>(blob), blobSize);
|
|
||||||
models.push_back(std::move(model));
|
|
||||||
result.nextRow();
|
result.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,9 +45,9 @@ void SQLiteDatabase::RemoveUnreferencedUgcModels() {
|
|||||||
|
|
||||||
void SQLiteDatabase::InsertNewUgcModel(
|
void SQLiteDatabase::InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data, // cant be const sad
|
std::stringstream& sd0Data, // cant be const sad
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) {
|
const LWOOBJID characterId) {
|
||||||
const std::istream stream(sd0Data.rdbuf());
|
const std::istream stream(sd0Data.rdbuf());
|
||||||
ExecuteInsert(
|
ExecuteInsert(
|
||||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||||
@@ -72,3 +70,14 @@ void SQLiteDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::stringstre
|
|||||||
const std::istream stream(lxfml.rdbuf());
|
const std::istream stream(lxfml.rdbuf());
|
||||||
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
ExecuteUpdate("UPDATE ugc SET lxfml = ? WHERE id = ?;", &stream, modelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<IUgc::Model> SQLiteDatabase::GetUgcModel(const LWOOBJID ugcId) {
|
||||||
|
auto [_, result] = ExecuteSelect("SELECT u.id AS ugcID, pc.id AS modelID, lxfml FROM ugc AS u JOIN properties_contents AS pc ON pc.id = u.id WHERE u.id = ?;", ugcId);
|
||||||
|
|
||||||
|
std::optional<IUgc::Model> toReturn = std::nullopt;
|
||||||
|
if (!result.eof()) {
|
||||||
|
toReturn = ReadModel(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) {
|
void SQLiteDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) {
|
||||||
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
ExecuteInsert("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)", bigId, modules, characterId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,27 +32,27 @@ std::vector<std::string> TestSQLDatabase::GetApprovedCharacterNames() {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<FriendData> TestSQLDatabase::GetFriendsList(uint32_t charID) {
|
std::vector<FriendData> TestSQLDatabase::GetFriendsList(LWOOBJID charID) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> TestSQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
std::optional<IFriends::BestFriendStatus> TestSQLDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) {
|
void TestSQLDatabase::SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
void TestSQLDatabase::AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
void TestSQLDatabase::RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
void TestSQLDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ void TestSQLDatabase::InsertMigration(const std::string_view str) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,11 +88,11 @@ std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const std::stri
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TestSQLDatabase::GetCharacterXml(const uint32_t accountId) {
|
std::string TestSQLDatabase::GetCharacterXml(const LWOOBJID accountId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
void TestSQLDatabase::UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,27 +104,27 @@ void TestSQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) {
|
void TestSQLDatabase::InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> TestSQLDatabase::GetAccountCharacterIds(uint32_t accountId) {
|
std::vector<LWOOBJID> TestSQLDatabase::GetAccountCharacterIds(LWOOBJID accountId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
void TestSQLDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
void TestSQLDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
void TestSQLDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
void TestSQLDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,11 +192,11 @@ void TestSQLDatabase::InsertNewMail(const MailInfo& mail) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::InsertNewUgcModel(std::stringstream& sd0Data, const uint32_t blueprintId, const uint32_t accountId, const uint32_t characterId) {
|
void TestSQLDatabase::InsertNewUgcModel(std::stringstream& sd0Data, const uint64_t blueprintId, const uint32_t accountId, const LWOOBJID characterId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MailInfo> TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
std::vector<MailInfo> TestSQLDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ std::optional<MailInfo> TestSQLDatabase::GetMail(const uint64_t mailId) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t TestSQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
uint32_t TestSQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ void TestSQLDatabase::ClaimMailItem(const uint64_t mailId) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
void TestSQLDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ void TestSQLDatabase::SetMasterInfo(const IServers::MasterInfo& info) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<uint32_t> TestSQLDatabase::GetCurrentPersistentId() {
|
std::optional<uint64_t> TestSQLDatabase::GetCurrentPersistentId() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,10 +252,6 @@ void TestSQLDatabase::InsertDefaultPersistentId() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::UpdatePersistentId(const uint32_t id) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<uint32_t> TestSQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
std::optional<uint32_t> TestSQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -268,15 +264,15 @@ std::vector<IUgc::Model> TestSQLDatabase::GetUgcModels(const LWOOBJID& propertyI
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void TestSQLDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
void TestSQLDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IIgnoreList::Info> TestSQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
std::vector<IIgnoreList::Info> TestSQLDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,3 +300,6 @@ void TestSQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGame
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IObjectIdTracker::Range TestSQLDatabase::GetPersistentIdRange() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,31 +17,31 @@ class TestSQLDatabase : public GameDatabase {
|
|||||||
|
|
||||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||||
|
|
||||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
||||||
|
|
||||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
||||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
||||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||||
void CreateMigrationHistoryTable() override;
|
void CreateMigrationHistoryTable() override;
|
||||||
bool IsMigrationRun(const std::string_view str) override;
|
bool IsMigrationRun(const std::string_view str) override;
|
||||||
void InsertMigration(const std::string_view str) override;
|
void InsertMigration(const std::string_view str) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
||||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
||||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
||||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||||
void DeleteCharacter(const uint32_t characterId) override;
|
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
||||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||||
@@ -60,30 +60,30 @@ class TestSQLDatabase : public GameDatabase {
|
|||||||
void InsertNewMail(const MailInfo& mail) override;
|
void InsertNewMail(const MailInfo& mail) override;
|
||||||
void InsertNewUgcModel(
|
void InsertNewUgcModel(
|
||||||
std::stringstream& sd0Data,
|
std::stringstream& sd0Data,
|
||||||
const uint32_t blueprintId,
|
const uint64_t blueprintId,
|
||||||
const uint32_t accountId,
|
const uint32_t accountId,
|
||||||
const uint32_t characterId) override;
|
const LWOOBJID characterId) override;
|
||||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
||||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
||||||
void MarkMailRead(const uint64_t mailId) override;
|
void MarkMailRead(const uint64_t mailId) override;
|
||||||
void DeleteMail(const uint64_t mailId) override;
|
void DeleteMail(const uint64_t mailId) override;
|
||||||
void ClaimMailItem(const uint64_t mailId) override;
|
void ClaimMailItem(const uint64_t mailId) override;
|
||||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
||||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint64_t> GetCurrentPersistentId() override;
|
||||||
|
IObjectIdTracker::Range GetPersistentIdRange() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
|
||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
void AddBehavior(const IBehaviors::Info& info) override;
|
void AddBehavior(const IBehaviors::Info& info) override;
|
||||||
@@ -95,17 +95,19 @@ class TestSQLDatabase : public GameDatabase {
|
|||||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override { return {}; };
|
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override { return {}; };
|
std::vector<ILeaderboard::Entry> GetNsLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override { return {}; };
|
std::vector<ILeaderboard::Entry> GetAgsLeaderboard(const uint32_t activityId) override { return {}; };
|
||||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override {};
|
void SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override {};
|
||||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override {};
|
void UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) override {};
|
||||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override { return {}; };
|
std::optional<ILeaderboard::Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) override { return {}; };
|
||||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override {};
|
void IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) override {};
|
||||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override {};
|
void IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) override {};
|
||||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override {};
|
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override {};
|
||||||
void DeleteUgcBuild(const LWOOBJID bigId) override {};
|
void DeleteUgcBuild(const LWOOBJID bigId) override {};
|
||||||
uint32_t GetAccountCount() override { return 0; };
|
uint32_t GetAccountCount() override { return 0; };
|
||||||
|
|
||||||
bool IsNameInUse(const std::string_view name) override { return false; };
|
bool IsNameInUse(const std::string_view name) override { return false; };
|
||||||
IPropertyContents::Model GetModel(const LWOOBJID modelID) override { return {}; }
|
std::optional<IPropertyContents::Model> GetModel(const LWOOBJID modelID) override { return {}; }
|
||||||
|
std::optional<IProperty::Info> GetPropertyInfo(const LWOOBJID id) override { return {}; }
|
||||||
|
std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) override { return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!TESTSQLDATABASE_H
|
#endif //!TESTSQLDATABASE_H
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ void ModelNormalizeMigration::Run() {
|
|||||||
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
||||||
const auto model = Database::Get()->GetModel(modelID);
|
const auto model = Database::Get()->GetModel(modelID);
|
||||||
// only BBB models (lot 14) and models with a position of NiPoint3::ZERO need to have their position fixed.
|
// only BBB models (lot 14) and models with a position of NiPoint3::ZERO need to have their position fixed.
|
||||||
if (model.position != NiPoint3Constant::ZERO || model.lot != 14) continue;
|
if (!model || model->position != NiPoint3Constant::ZERO || model->lot != 14) continue;
|
||||||
|
|
||||||
Sd0 sd0(lxfmlData);
|
Sd0 sd0(lxfmlData);
|
||||||
const auto asStr = sd0.GetAsStringUncompressed();
|
const auto asStr = sd0.GetAsStringUncompressed();
|
||||||
@@ -23,7 +23,7 @@ void ModelNormalizeMigration::Run() {
|
|||||||
LOG("Updated model %llu to have a center of %f %f %f", modelID, newCenter.x, newCenter.y, newCenter.z);
|
LOG("Updated model %llu to have a center of %f %f %f", modelID, newCenter.x, newCenter.y, newCenter.z);
|
||||||
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
||||||
auto asStream = sd0.GetAsStream();
|
auto asStream = sd0.GetAsStream();
|
||||||
Database::Get()->UpdateModel(model.id, newCenter, model.rotation, model.behaviors);
|
Database::Get()->UpdateModel(model->id, newCenter, model->rotation, model->behaviors);
|
||||||
Database::Get()->UpdateUgcModelData(id, asStream);
|
Database::Get()->UpdateUgcModelData(id, asStream);
|
||||||
}
|
}
|
||||||
Database::Get()->SetAutoCommit(oldCommit);
|
Database::Get()->SetAutoCommit(oldCommit);
|
||||||
@@ -35,15 +35,15 @@ void ModelNormalizeMigration::RunAfterFirstPart() {
|
|||||||
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
||||||
const auto model = Database::Get()->GetModel(modelID);
|
const auto model = Database::Get()->GetModel(modelID);
|
||||||
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
||||||
if (model.lot != 14) continue;
|
if (!model || model->lot != 14) continue;
|
||||||
|
|
||||||
Sd0 sd0(lxfmlData);
|
Sd0 sd0(lxfmlData);
|
||||||
const auto asStr = sd0.GetAsStringUncompressed();
|
const auto asStr = sd0.GetAsStringUncompressed();
|
||||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePositionAfterFirstPart(asStr, model.position);
|
const auto [newLxfml, newCenter] = Lxfml::NormalizePositionAfterFirstPart(asStr, model->position);
|
||||||
|
|
||||||
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
||||||
auto asStream = sd0.GetAsStream();
|
auto asStream = sd0.GetAsStream();
|
||||||
Database::Get()->UpdateModel(model.id, newCenter, model.rotation, model.behaviors);
|
Database::Get()->UpdateModel(model->id, newCenter, model->rotation, model->behaviors);
|
||||||
Database::Get()->UpdateUgcModelData(id, asStream);
|
Database::Get()->UpdateUgcModelData(id, asStream);
|
||||||
}
|
}
|
||||||
Database::Get()->SetAutoCommit(oldCommit);
|
Database::Get()->SetAutoCommit(oldCommit);
|
||||||
@@ -55,16 +55,16 @@ void ModelNormalizeMigration::RunBrickBuildGrid() {
|
|||||||
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
||||||
const auto model = Database::Get()->GetModel(modelID);
|
const auto model = Database::Get()->GetModel(modelID);
|
||||||
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
||||||
if (model.lot != 14) continue;
|
if (!model || model->lot != 14) continue;
|
||||||
|
|
||||||
Sd0 sd0(lxfmlData);
|
Sd0 sd0(lxfmlData);
|
||||||
const auto asStr = sd0.GetAsStringUncompressed();
|
const auto asStr = sd0.GetAsStringUncompressed();
|
||||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePosition(asStr, model.position);
|
const auto [newLxfml, newCenter] = Lxfml::NormalizePosition(asStr, model->position);
|
||||||
|
|
||||||
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
||||||
LOG("Updated model %llu to have a center of %f %f %f", modelID, newCenter.x, newCenter.y, newCenter.z);
|
LOG("Updated model %llu to have a center of %f %f %f", modelID, newCenter.x, newCenter.y, newCenter.z);
|
||||||
auto asStream = sd0.GetAsStream();
|
auto asStream = sd0.GetAsStream();
|
||||||
Database::Get()->UpdateModel(model.id, newCenter, model.rotation, model.behaviors);
|
Database::Get()->UpdateModel(model->id, newCenter, model->rotation, model->behaviors);
|
||||||
Database::Get()->UpdateUgcModelData(id, asStream);
|
Database::Get()->UpdateUgcModelData(id, asStream);
|
||||||
}
|
}
|
||||||
Database::Get()->SetAutoCommit(oldCommit);
|
Database::Get()->SetAutoCommit(oldCommit);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
#include "CDPlayerFlagsTable.h"
|
#include "CDPlayerFlagsTable.h"
|
||||||
|
|
||||||
Character::Character(uint32_t id, User* parentUser) {
|
Character::Character(LWOOBJID id, User* parentUser) {
|
||||||
//First load the name, etc:
|
//First load the name, etc:
|
||||||
m_ID = id;
|
m_ID = id;
|
||||||
m_ParentUser = parentUser;
|
m_ParentUser = parentUser;
|
||||||
@@ -50,6 +50,10 @@ void Character::UpdateInfoFromDatabase() {
|
|||||||
|
|
||||||
//Load the xmlData now:
|
//Load the xmlData now:
|
||||||
m_XMLData = Database::Get()->GetCharacterXml(m_ID);
|
m_XMLData = Database::Get()->GetCharacterXml(m_ID);
|
||||||
|
if (m_XMLData.empty()) {
|
||||||
|
LOG("Character %s (%llu) has no xml data!", m_Name.c_str(), m_ID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_ZoneID = 0; //TEMP! Set back to 0 when done. This is so we can see loading screen progress for testing.
|
m_ZoneID = 0; //TEMP! Set back to 0 when done. This is so we can see loading screen progress for testing.
|
||||||
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
|
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
|
||||||
@@ -61,7 +65,6 @@ void Character::UpdateInfoFromDatabase() {
|
|||||||
//Set our objectID:
|
//Set our objectID:
|
||||||
m_ObjectID = m_ID;
|
m_ObjectID = m_ID;
|
||||||
GeneralUtils::SetBit(m_ObjectID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(m_ObjectID, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(m_ObjectID, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
m_OurEntity = nullptr;
|
m_OurEntity = nullptr;
|
||||||
m_BuildMode = false;
|
m_BuildMode = false;
|
||||||
@@ -75,7 +78,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
if (m_XMLData.size() == 0) return;
|
if (m_XMLData.size() == 0) return;
|
||||||
|
|
||||||
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
||||||
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
|
LOG("Loaded xmlData for character %s (%llu)!", m_Name.c_str(), m_ID);
|
||||||
} else {
|
} else {
|
||||||
LOG("Failed to load xmlData (%i) (%s) (%s)!", m_Doc.ErrorID(), m_Doc.ErrorIDToName(m_Doc.ErrorID()), m_Doc.ErrorStr());
|
LOG("Failed to load xmlData (%i) (%s) (%s)!", m_Doc.ErrorID(), m_Doc.ErrorIDToName(m_Doc.ErrorID()), m_Doc.ErrorStr());
|
||||||
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
|
//Server::rakServer->CloseConnection(m_ParentUser->GetSystemAddress(), true);
|
||||||
@@ -238,7 +241,7 @@ void Character::SetBuildMode(bool buildMode) {
|
|||||||
void Character::SaveXMLToDatabase() {
|
void Character::SaveXMLToDatabase() {
|
||||||
// Check that we can actually _save_ before saving
|
// Check that we can actually _save_ before saving
|
||||||
if (!m_OurEntity) {
|
if (!m_OurEntity) {
|
||||||
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
LOG("%llu:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +311,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
//For metrics, log the time it took to save:
|
//For metrics, log the time it took to save:
|
||||||
auto end = std::chrono::system_clock::now();
|
auto end = std::chrono::system_clock::now();
|
||||||
std::chrono::duration<double> elapsed = end - start;
|
std::chrono::duration<double> elapsed = end - start;
|
||||||
LOG("%i:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count());
|
LOG("%llu:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::SetIsNewLogin() {
|
void Character::SetIsNewLogin() {
|
||||||
@@ -320,7 +323,7 @@ void Character::SetIsNewLogin() {
|
|||||||
while (currentChild) {
|
while (currentChild) {
|
||||||
auto* nextChild = currentChild->NextSiblingElement();
|
auto* nextChild = currentChild->NextSiblingElement();
|
||||||
if (currentChild->Attribute("si")) {
|
if (currentChild->Attribute("si")) {
|
||||||
LOG("Removed session flag (%s) from character %i:%s, saving character to database", currentChild->Attribute("si"), GetID(), GetName().c_str());
|
LOG("Removed session flag (%s) from character %llu:%s, saving character to database", currentChild->Attribute("si"), GetID(), GetName().c_str());
|
||||||
flags->DeleteChild(currentChild);
|
flags->DeleteChild(currentChild);
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
}
|
}
|
||||||
@@ -333,8 +336,11 @@ void Character::WriteToDatabase() {
|
|||||||
tinyxml2::XMLPrinter printer(0, true, 0);
|
tinyxml2::XMLPrinter printer(0, true, 0);
|
||||||
m_Doc.Print(&printer);
|
m_Doc.Print(&printer);
|
||||||
|
|
||||||
|
// Update the xml on the character for future use if needed
|
||||||
|
m_XMLData = printer.CStr();
|
||||||
|
|
||||||
//Finally, save to db:
|
//Finally, save to db:
|
||||||
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
|
Database::Get()->UpdateCharacterXml(m_ID, m_XMLData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
|
void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
|
||||||
@@ -496,7 +502,7 @@ void Character::OnZoneLoad() {
|
|||||||
|
|
||||||
// Remove all GM items
|
// Remove all GM items
|
||||||
for (const auto lot : Inventory::GetAllGMItems()) {
|
for (const auto lot : Inventory::GetAllGMItems()) {
|
||||||
inventoryComponent->RemoveItem(lot, inventoryComponent->GetLotCount(lot));
|
inventoryComponent->RemoveItem(lot, inventoryComponent->GetLotCount(lot), eInventoryType::ALL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ enum class eLootSourceType : uint32_t;
|
|||||||
*/
|
*/
|
||||||
class Character {
|
class Character {
|
||||||
public:
|
public:
|
||||||
Character(uint32_t id, User* parentUser);
|
Character(LWOOBJID id, User* parentUser);
|
||||||
~Character();
|
~Character();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
* Gets the database ID of the character
|
* Gets the database ID of the character
|
||||||
* @return the database ID of the character
|
* @return the database ID of the character
|
||||||
*/
|
*/
|
||||||
uint32_t GetID() const { return m_ID; }
|
LWOOBJID GetID() const { return m_ID; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the (custom) name of the character
|
* Gets the (custom) name of the character
|
||||||
@@ -467,9 +467,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
void UpdateInfoFromDatabase();
|
void UpdateInfoFromDatabase();
|
||||||
/**
|
/**
|
||||||
* The ID of this character. First 32 bits of the ObjectID.
|
* The ID of this character.
|
||||||
*/
|
*/
|
||||||
uint32_t m_ID{};
|
LWOOBJID m_ID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 64-bit unique ID used in the game.
|
* The 64-bit unique ID used in the game.
|
||||||
@@ -654,7 +654,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The spawn rotation of this character when loading in
|
* The spawn rotation of this character when loading in
|
||||||
*/
|
*/
|
||||||
NiQuaternion m_OriginalRotation;
|
NiQuaternion m_OriginalRotation = QuatUtils::IDENTITY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The respawn points of this character, per world
|
* The respawn points of this character, per world
|
||||||
@@ -682,6 +682,9 @@ private:
|
|||||||
* NOTE: quick as there's no DB lookups
|
* NOTE: quick as there's no DB lookups
|
||||||
*/
|
*/
|
||||||
void DoQuickXMLDataParse();
|
void DoQuickXMLDataParse();
|
||||||
|
public:
|
||||||
|
const decltype(m_PlayerFlags)& GetPlayerFlags() const { return m_PlayerFlags; }
|
||||||
|
const decltype(m_SessionFlags)& GetSessionFlags() const { return m_SessionFlags; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CHARACTER_H
|
#endif // CHARACTER_H
|
||||||
|
|||||||
345
dGame/Entity.cpp
345
dGame/Entity.cpp
@@ -84,6 +84,8 @@
|
|||||||
#include "GhostComponent.h"
|
#include "GhostComponent.h"
|
||||||
#include "AchievementVendorComponent.h"
|
#include "AchievementVendorComponent.h"
|
||||||
#include "VanityUtilities.h"
|
#include "VanityUtilities.h"
|
||||||
|
#include "ObjectIDManager.h"
|
||||||
|
#include "ePlayerFlag.h"
|
||||||
|
|
||||||
// Table includes
|
// Table includes
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
@@ -175,8 +177,11 @@ Entity::~Entity() {
|
|||||||
CancelAllTimers();
|
CancelAllTimers();
|
||||||
CancelCallbackTimers();
|
CancelCallbackTimers();
|
||||||
|
|
||||||
for (const auto& component : m_Components | std::views::values) {
|
for (auto& component : m_Components | std::views::values) {
|
||||||
if (component) delete component;
|
if (component) {
|
||||||
|
delete component;
|
||||||
|
component = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* const child : m_ChildEntities) {
|
for (auto* const child : m_ChildEntities) {
|
||||||
@@ -184,19 +189,27 @@ Entity::~Entity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_ParentEntity) {
|
if (m_ParentEntity) {
|
||||||
|
GameMessages::ChildRemoved removedMsg{};
|
||||||
|
removedMsg.childID = m_ObjectID;
|
||||||
|
removedMsg.target = m_ParentEntity->GetObjectID();
|
||||||
|
removedMsg.Send();
|
||||||
m_ParentEntity->RemoveChild(this);
|
m_ParentEntity->RemoveChild(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::Initialize() {
|
void Entity::Initialize() {
|
||||||
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &Entity::MsgRequestServerObjectInfo);
|
RegisterMsg<GameMessages::RequestServerObjectInfo>(this, &Entity::MsgRequestServerObjectInfo);
|
||||||
|
RegisterMsg<GameMessages::DropClientLoot>(this, &Entity::MsgDropClientLoot);
|
||||||
|
RegisterMsg<GameMessages::GetFactionTokenType>(this, &Entity::MsgGetFactionTokenType);
|
||||||
|
RegisterMsg<GameMessages::PickupItem>(this, &Entity::MsgPickupItem);
|
||||||
|
RegisterMsg<GameMessages::ChildRemoved>(this, &Entity::MsgChildRemoved);
|
||||||
/**
|
/**
|
||||||
* Setup trigger
|
* Setup trigger
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const auto triggerInfo = GetVarAsString(u"trigger_id");
|
const auto triggerInfo = GetVarAsString(u"trigger_id");
|
||||||
|
|
||||||
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(triggerInfo);
|
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(-1, triggerInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup groups
|
* Setup groups
|
||||||
@@ -231,11 +244,11 @@ void Entity::Initialize() {
|
|||||||
|
|
||||||
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
||||||
|
|
||||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
AddComponent<ModelComponent>(-1)->LoadBehaviors();
|
||||||
|
|
||||||
AddComponent<RenderComponent>();
|
AddComponent<RenderComponent>(-1);
|
||||||
|
|
||||||
auto* destroyableComponent = AddComponent<DestroyableComponent>();
|
auto* destroyableComponent = AddComponent<DestroyableComponent>(-1);
|
||||||
destroyableComponent->SetHealth(1);
|
destroyableComponent->SetHealth(1);
|
||||||
destroyableComponent->SetMaxHealth(1.0f);
|
destroyableComponent->SetMaxHealth(1.0f);
|
||||||
destroyableComponent->SetFaction(-1, true);
|
destroyableComponent->SetFaction(-1, true);
|
||||||
@@ -251,37 +264,42 @@ void Entity::Initialize() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (m_Character && m_Character->GetParentUser()) {
|
if (m_Character && m_Character->GetParentUser()) {
|
||||||
AddComponent<MissionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
|
AddComponent<MissionComponent>(-1)->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t petComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET);
|
const auto petComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET);
|
||||||
if (petComponentId > 0) {
|
if (petComponentID > 0) {
|
||||||
AddComponent<PetComponent>(petComponentId);
|
AddComponent<PetComponent>(petComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL) > 0) {
|
const auto minigameControlID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL);
|
||||||
AddComponent<MiniGameControlComponent>();
|
if (minigameControlID > 0) {
|
||||||
|
AddComponent<MiniGameControlComponent>(minigameControlID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
|
const auto possessableComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
|
||||||
if (possessableComponentId > 0) {
|
if (possessableComponentID > 0) {
|
||||||
AddComponent<PossessableComponent>(possessableComponentId);
|
AddComponent<PossessableComponent>(possessableComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY) > 0) {
|
const auto moduleAssemblyID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY);
|
||||||
AddComponent<ModuleAssemblyComponent>();
|
if (moduleAssemblyID > 0) {
|
||||||
|
AddComponent<ModuleAssemblyComponent>(moduleAssemblyID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS) > 0) {
|
const auto racingStatsID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS);
|
||||||
AddComponent<RacingStatsComponent>();
|
if (racingStatsID > 0) {
|
||||||
|
AddComponent<RacingStatsComponent>(racingStatsID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1) >= 0) {
|
const auto lupExhibitID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1);
|
||||||
AddComponent<LUPExhibitComponent>();
|
if (lupExhibitID >= 0) {
|
||||||
|
AddComponent<LUPExhibitComponent>(lupExhibitID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL) > 0) {
|
const auto racingControlID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL);
|
||||||
AddComponent<RacingControlComponent>();
|
if (racingControlID > 0) {
|
||||||
|
AddComponent<RacingControlComponent>(racingControlID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE);
|
const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE);
|
||||||
@@ -289,7 +307,7 @@ void Entity::Initialize() {
|
|||||||
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
|
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
const auto controllablePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
||||||
if (controllablePhysicsComponentID > 0) {
|
if (controllablePhysicsComponentID > 0) {
|
||||||
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>(controllablePhysicsComponentID);
|
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>(controllablePhysicsComponentID);
|
||||||
|
|
||||||
@@ -301,7 +319,7 @@ void Entity::Initialize() {
|
|||||||
//If we came from another zone, put us in the starting loc
|
//If we came from another zone, put us in the starting loc
|
||||||
if (m_Character->GetZoneID() != Game::server->GetZoneID() || mapID == 1603) { // Exception for Moon Base as you tend to spawn on the roof.
|
if (m_Character->GetZoneID() != Game::server->GetZoneID() || mapID == 1603) { // Exception for Moon Base as you tend to spawn on the roof.
|
||||||
NiPoint3 pos;
|
NiPoint3 pos;
|
||||||
NiQuaternion rot;
|
NiQuaternion rot = QuatUtils::IDENTITY;
|
||||||
|
|
||||||
const auto& targetSceneName = m_Character->GetTargetScene();
|
const auto& targetSceneName = m_Character->GetTargetScene();
|
||||||
auto* targetScene = Game::entityManager->GetSpawnPointEntity(targetSceneName);
|
auto* targetScene = Game::entityManager->GetSpawnPointEntity(targetSceneName);
|
||||||
@@ -334,46 +352,48 @@ void Entity::Initialize() {
|
|||||||
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
|
const auto rigidBodyPhantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS);
|
||||||
if (rigidBodyPhantomPhysicsComponentID > 0) {
|
if (rigidBodyPhantomPhysicsComponentID > 0) {
|
||||||
AddComponent<RigidbodyPhantomPhysicsComponent>(rigidBodyPhantomPhysicsComponentID);
|
AddComponent<RigidbodyPhantomPhysicsComponent>(rigidBodyPhantomPhysicsComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
|
const auto phantomPhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS);
|
||||||
if (markedAsPhantom || phantomPhysicsComponentID > 0) {
|
if (markedAsPhantom || phantomPhysicsComponentID > 0) {
|
||||||
AddComponent<PhantomPhysicsComponent>(phantomPhysicsComponentID)->SetPhysicsEffectActive(false);
|
AddComponent<PhantomPhysicsComponent>(phantomPhysicsComponentID)->SetPhysicsEffectActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
|
const auto havokVehiclePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS);
|
||||||
if (havokVehiclePhysicsComponentID > 0) {
|
if (havokVehiclePhysicsComponentID > 0) {
|
||||||
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(havokVehiclePhysicsComponentID);
|
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(havokVehiclePhysicsComponentID);
|
||||||
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
|
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
|
||||||
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
|
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
|
const auto soundTriggerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1);
|
||||||
AddComponent<SoundTriggerComponent>();
|
const auto racingSoundTriggerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1);
|
||||||
} else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) {
|
if (soundTriggerID > -1) {
|
||||||
AddComponent<RacingSoundTriggerComponent>();
|
AddComponent<SoundTriggerComponent>(soundTriggerID);
|
||||||
|
} else if (racingSoundTriggerID > -1) {
|
||||||
|
AddComponent<RacingSoundTriggerComponent>(racingSoundTriggerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF) > 0) {
|
const auto buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
|
||||||
AddComponent<BuffComponent>();
|
if (buffComponentID > 0) {
|
||||||
|
AddComponent<BuffComponent>(buffComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE);
|
const auto collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE);
|
||||||
|
|
||||||
if (collectibleComponentID > 0) {
|
if (collectibleComponentID > 0) {
|
||||||
AddComponent<CollectibleComponent>(GetVarAs<int32_t>(u"collectible_id"));
|
AddComponent<CollectibleComponent>(collectibleComponentID, GetVarAs<int32_t>(u"collectible_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiple components require the destructible component.
|
* Multiple components require the destructible component.
|
||||||
*/
|
*/
|
||||||
const int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
|
const auto quickBuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
|
||||||
const int quickBuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
|
|
||||||
|
|
||||||
int componentID = -1;
|
int32_t componentID = -1;
|
||||||
if (collectibleComponentID > 0) componentID = collectibleComponentID;
|
if (collectibleComponentID > 0) componentID = collectibleComponentID;
|
||||||
if (quickBuildComponentID > 0) componentID = quickBuildComponentID;
|
if (quickBuildComponentID > 0) componentID = quickBuildComponentID;
|
||||||
if (buffComponentID > 0) componentID = buffComponentID;
|
if (buffComponentID > 0) componentID = buffComponentID;
|
||||||
@@ -381,7 +401,7 @@ void Entity::Initialize() {
|
|||||||
|
|
||||||
bool isSmashable = GetVarAs<int32_t>(u"is_smashable") != 0;
|
bool isSmashable = GetVarAs<int32_t>(u"is_smashable") != 0;
|
||||||
if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) {
|
if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) {
|
||||||
DestroyableComponent* comp = AddComponent<DestroyableComponent>();
|
DestroyableComponent* comp = AddComponent<DestroyableComponent>(componentID);
|
||||||
auto* const destCompTable = CDClientManager::GetTable<CDDestructibleComponentTable>();
|
auto* const destCompTable = CDClientManager::GetTable<CDDestructibleComponentTable>();
|
||||||
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([componentID](const CDDestructibleComponent& entry) { return (entry.id == componentID); });
|
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([componentID](const CDDestructibleComponent& entry) { return (entry.id == componentID); });
|
||||||
|
|
||||||
@@ -409,6 +429,7 @@ void Entity::Initialize() {
|
|||||||
comp->SetIsSmashable(destCompData[0].isSmashable);
|
comp->SetIsSmashable(destCompData[0].isSmashable);
|
||||||
|
|
||||||
comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
|
comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
|
||||||
|
comp->SetCurrencyIndex(destCompData[0].CurrencyIndex);
|
||||||
Loot::CacheMatrix(destCompData[0].LootMatrixIndex);
|
Loot::CacheMatrix(destCompData[0].LootMatrixIndex);
|
||||||
|
|
||||||
// Now get currency information
|
// Now get currency information
|
||||||
@@ -470,27 +491,30 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER) > 0 || m_Character) {
|
const auto characterID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER);
|
||||||
|
if (characterID > 0 || m_Character) {
|
||||||
// Character Component always has a possessor, level, and forced movement components
|
// Character Component always has a possessor, level, and forced movement components
|
||||||
AddComponent<PossessorComponent>();
|
AddComponent<PossessorComponent>(characterID);
|
||||||
|
|
||||||
// load in the xml for the level
|
// load in the xml for the level
|
||||||
AddComponent<LevelProgressionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
|
AddComponent<LevelProgressionComponent>(characterID)->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
|
|
||||||
AddComponent<PlayerForcedMovementComponent>();
|
AddComponent<PlayerForcedMovementComponent>(characterID);
|
||||||
|
|
||||||
auto& systemAddress = m_Character->GetParentUser() ? m_Character->GetParentUser()->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
|
auto& systemAddress = m_Character->GetParentUser() ? m_Character->GetParentUser()->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
|
||||||
AddComponent<CharacterComponent>(m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc());
|
AddComponent<CharacterComponent>(characterID, m_Character, systemAddress)->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
|
|
||||||
AddComponent<GhostComponent>();
|
AddComponent<GhostComponent>(characterID)->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
|
const auto inventoryID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY);
|
||||||
AddComponent<InventoryComponent>();
|
if (inventoryID > 0 || m_Character) {
|
||||||
|
AddComponent<InventoryComponent>(inventoryID);
|
||||||
}
|
}
|
||||||
// if this component exists, then we initialize it. it's value is always 0
|
// if this component exists, then we initialize it. it's value is always 0
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
|
const auto multiZoneEntranceID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1);
|
||||||
AddComponent<MultiZoneEntranceComponent>();
|
if (multiZoneEntranceID > -1) {
|
||||||
|
AddComponent<MultiZoneEntranceComponent>(multiZoneEntranceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -542,7 +566,7 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!scriptName.empty() || client || m_Character || scriptComponentID >= 0) {
|
if (!scriptName.empty() || client || m_Character || scriptComponentID >= 0) {
|
||||||
AddComponent<ScriptComponent>(scriptName, true, client && scriptName.empty());
|
AddComponent<ScriptComponent>(scriptComponentID, scriptName, true, client && scriptName.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZoneControl script
|
// ZoneControl script
|
||||||
@@ -551,26 +575,27 @@ void Entity::Initialize() {
|
|||||||
const CDZoneTable* const zoneData = CDZoneTableTable::Query(zoneID.GetMapID());
|
const CDZoneTable* const zoneData = CDZoneTableTable::Query(zoneID.GetMapID());
|
||||||
|
|
||||||
if (zoneData != nullptr) {
|
if (zoneData != nullptr) {
|
||||||
int zoneScriptID = zoneData->scriptID;
|
const int32_t zoneScriptID = zoneData->scriptID;
|
||||||
CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
|
CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
|
||||||
AddComponent<ScriptComponent>(zoneScriptData.script_name, true);
|
AddComponent<ScriptComponent>(zoneScriptID, zoneScriptData.script_name, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1) != -1 || m_Character) {
|
const auto skillID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1);
|
||||||
AddComponent<SkillComponent>();
|
if (skillID > -1 || m_Character) {
|
||||||
|
AddComponent<SkillComponent>(skillID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto combatAiId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI);
|
const auto combatAiID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI);
|
||||||
if (combatAiId > 0) {
|
if (combatAiID > 0) {
|
||||||
AddComponent<BaseCombatAIComponent>(combatAiId);
|
AddComponent<BaseCombatAIComponent>(combatAiID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) {
|
if (quickBuildComponentID > 0) {
|
||||||
auto* const quickBuildComponent = AddComponent<QuickBuildComponent>();
|
auto* const quickBuildComponent = AddComponent<QuickBuildComponent>(quickBuildComponentID);
|
||||||
|
|
||||||
CDRebuildComponentTable* const rebCompTable = CDClientManager::GetTable<CDRebuildComponentTable>();
|
CDRebuildComponentTable* const rebCompTable = CDClientManager::GetTable<CDRebuildComponentTable>();
|
||||||
const std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == quickBuildComponentID); });
|
const std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([quickBuildComponentID](CDRebuildComponent entry) { return (entry.id == quickBuildComponentID); });
|
||||||
|
|
||||||
if (!rebCompData.empty()) {
|
if (!rebCompData.empty()) {
|
||||||
quickBuildComponent->SetResetTime(rebCompData[0].reset_time);
|
quickBuildComponent->SetResetTime(rebCompData[0].reset_time);
|
||||||
@@ -615,53 +640,63 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) {
|
const auto switchID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1);
|
||||||
AddComponent<SwitchComponent>();
|
if (switchID > -1) {
|
||||||
|
AddComponent<SwitchComponent>(switchID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
|
const auto vendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR);
|
||||||
AddComponent<VendorComponent>();
|
const auto donationVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1);
|
||||||
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
|
const auto achievementVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1);
|
||||||
AddComponent<DonationVendorComponent>();
|
if (vendorID > 0) {
|
||||||
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1) != -1)) {
|
AddComponent<VendorComponent>(vendorID);
|
||||||
AddComponent<AchievementVendorComponent>();
|
} else if (donationVendorID > -1) {
|
||||||
|
AddComponent<DonationVendorComponent>(donationVendorID);
|
||||||
|
} else if (achievementVendorID > -1) {
|
||||||
|
AddComponent<AchievementVendorComponent>(achievementVendorID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
|
const auto propertyVendorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1);
|
||||||
AddComponent<PropertyVendorComponent>();
|
if (propertyVendorID > -1) {
|
||||||
|
AddComponent<PropertyVendorComponent>(propertyVendorID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1) != -1) {
|
const auto propertyManagementID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1);
|
||||||
AddComponent<PropertyManagementComponent>();
|
if (propertyManagementID > -1) {
|
||||||
|
AddComponent<PropertyManagementComponent>(propertyManagementID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1) != -1) { // you have to determine it like this because all bouncers have a componentID of 0
|
const auto bouncerID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1);
|
||||||
AddComponent<BouncerComponent>();
|
if (bouncerID > -1) { // you have to determine it like this because all bouncers have a componentID of 0
|
||||||
|
AddComponent<BouncerComponent>(bouncerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
|
const auto renderComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
|
||||||
if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) {
|
if ((renderComponentID > 0 && m_TemplateID != 2365) || m_Character) {
|
||||||
AddComponent<RenderComponent>(renderComponentId);
|
AddComponent<RenderComponent>(renderComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER) > 0) || m_Character) {
|
const auto missionOfferComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER, -1);
|
||||||
AddComponent<MissionOfferComponent>(m_TemplateID);
|
if (missionOfferComponentID > -1 || m_Character) {
|
||||||
|
AddComponent<MissionOfferComponent>(missionOfferComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1) != -1) {
|
const auto buildBorderID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1);
|
||||||
AddComponent<BuildBorderComponent>();
|
if (buildBorderID > -1) {
|
||||||
|
AddComponent<BuildBorderComponent>(buildBorderID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scripted activity component
|
// Scripted activity component
|
||||||
const int32_t scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY, -1);
|
const auto scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY, -1);
|
||||||
if (scriptedActivityID != -1) {
|
if (scriptedActivityID > -1) {
|
||||||
AddComponent<ScriptedActivityComponent>(scriptedActivityID);
|
AddComponent<ScriptedActivityComponent>(scriptedActivityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent<PetComponent>()) {
|
const auto modelID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1);
|
||||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
if (modelID > -1 && !GetComponent<PetComponent>()) {
|
||||||
|
AddComponent<ModelComponent>(modelID)->LoadBehaviors();
|
||||||
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
|
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
|
||||||
auto* const destroyableComponent = AddComponent<DestroyableComponent>();
|
auto* const destroyableComponent = AddComponent<DestroyableComponent>(-1);
|
||||||
destroyableComponent->SetHealth(1);
|
destroyableComponent->SetHealth(1);
|
||||||
destroyableComponent->SetMaxHealth(1.0f);
|
destroyableComponent->SetMaxHealth(1.0f);
|
||||||
destroyableComponent->SetFaction(-1, true);
|
destroyableComponent->SetFaction(-1, true);
|
||||||
@@ -669,9 +704,10 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PetComponent* petComponent;
|
PetComponent* petComponent{};
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
|
const auto itemID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM);
|
||||||
AddComponent<ItemComponent>();
|
if (itemID > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
|
||||||
|
AddComponent<ItemComponent>(itemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shooting gallery component
|
// Shooting gallery component
|
||||||
@@ -680,16 +716,17 @@ void Entity::Initialize() {
|
|||||||
AddComponent<ShootingGalleryComponent>(shootingGalleryComponentID);
|
AddComponent<ShootingGalleryComponent>(shootingGalleryComponentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) {
|
const auto propertyID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1);
|
||||||
AddComponent<PropertyComponent>();
|
if (propertyID > -1) {
|
||||||
|
AddComponent<PropertyComponent>(propertyID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int rocketId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH);
|
const auto rocketID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH);
|
||||||
if ((rocketId > 0)) {
|
if ((rocketID > 0)) {
|
||||||
AddComponent<RocketLaunchpadControlComponent>(rocketId);
|
AddComponent<RocketLaunchpadControlComponent>(rocketID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR);
|
const auto railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR);
|
||||||
if (railComponentID > 0) {
|
if (railComponentID > 0) {
|
||||||
AddComponent<RailActivatorComponent>(railComponentID);
|
AddComponent<RailActivatorComponent>(railComponentID);
|
||||||
}
|
}
|
||||||
@@ -719,9 +756,9 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddComponent<MovementAIComponent>(moveInfo);
|
AddComponent<MovementAIComponent>(movementAIID, moveInfo);
|
||||||
}
|
}
|
||||||
} else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
|
} else if (petComponentID > 0 || combatAiID > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
|
||||||
MovementAIInfo moveInfo{
|
MovementAIInfo moveInfo{
|
||||||
.movementType = "",
|
.movementType = "",
|
||||||
.wanderRadius = 16,
|
.wanderRadius = 16,
|
||||||
@@ -731,7 +768,7 @@ void Entity::Initialize() {
|
|||||||
.wanderDelayMax = 5,
|
.wanderDelayMax = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddComponent<MovementAIComponent>(moveInfo);
|
AddComponent<MovementAIComponent>(-1, moveInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string pathName = GetVarAsString(u"attached_path");
|
const std::string pathName = GetVarAsString(u"attached_path");
|
||||||
@@ -741,10 +778,10 @@ void Entity::Initialize() {
|
|||||||
if (path) {
|
if (path) {
|
||||||
// if we have a moving platform path, then we need a moving platform component
|
// if we have a moving platform path, then we need a moving platform component
|
||||||
if (path->pathType == PathType::MovingPlatform) {
|
if (path->pathType == PathType::MovingPlatform) {
|
||||||
AddComponent<MovingPlatformComponent>(pathName);
|
AddComponent<MovingPlatformComponent>(-1, pathName);
|
||||||
} else if (path->pathType == PathType::Movement) {
|
} else if (path->pathType == PathType::Movement) {
|
||||||
auto* const movementAIcomponent = GetComponent<MovementAIComponent>();
|
auto* const movementAIcomponent = GetComponent<MovementAIComponent>();
|
||||||
if (movementAIcomponent && combatAiId == 0) {
|
if (movementAIcomponent && combatAiID == 0) {
|
||||||
movementAIcomponent->SetPath(pathName);
|
movementAIcomponent->SetPath(pathName);
|
||||||
} else {
|
} else {
|
||||||
MovementAIInfo moveInfo{
|
MovementAIInfo moveInfo{
|
||||||
@@ -756,24 +793,24 @@ void Entity::Initialize() {
|
|||||||
.wanderDelayMax = 5,
|
.wanderDelayMax = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddComponent<MovementAIComponent>(moveInfo);
|
AddComponent<MovementAIComponent>(-1, moveInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// else we still need to setup moving platform if it has a moving platform comp but no path
|
// else we still need to setup moving platform if it has a moving platform comp but no path
|
||||||
const int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
|
const auto movingPlatformComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
|
||||||
if (movingPlatformComponentId >= 0) {
|
if (movingPlatformComponentID >= 0) {
|
||||||
AddComponent<MovingPlatformComponent>(pathName);
|
AddComponent<MovingPlatformComponent>(movingPlatformComponentID, pathName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
|
const auto proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
|
||||||
if (proximityMonitorID > 0) {
|
if (proximityMonitorID > 0) {
|
||||||
auto* const proxCompTable = CDClientManager::GetTable<CDProximityMonitorComponentTable>();
|
auto* const proxCompTable = CDClientManager::GetTable<CDProximityMonitorComponentTable>();
|
||||||
const auto proxCompData = proxCompTable->Query([proximityMonitorID](const CDProximityMonitorComponent& entry) { return (entry.id == proximityMonitorID); });
|
const auto proxCompData = proxCompTable->Query([proximityMonitorID](const CDProximityMonitorComponent& entry) { return (entry.id == proximityMonitorID); });
|
||||||
if (proxCompData.size() > 0) {
|
if (proxCompData.size() > 0) {
|
||||||
std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
|
std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
|
||||||
AddComponent<ProximityMonitorComponent>(std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
|
AddComponent<ProximityMonitorComponent>(proximityMonitorID, std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,12 +916,13 @@ void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationNa
|
|||||||
|
|
||||||
void Entity::SetProximityRadius(float proxRadius, std::string name) {
|
void Entity::SetProximityRadius(float proxRadius, std::string name) {
|
||||||
auto* proxMon = GetComponent<ProximityMonitorComponent>();
|
auto* proxMon = GetComponent<ProximityMonitorComponent>();
|
||||||
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>();
|
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>(-1);
|
||||||
proxMon->SetProximityRadius(proxRadius, name);
|
proxMon->SetProximityRadius(proxRadius, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::SetProximityRadius(dpEntity* entity, std::string name) {
|
void Entity::SetProximityRadius(dpEntity* entity, std::string name) {
|
||||||
ProximityMonitorComponent* proxMon = AddComponent<ProximityMonitorComponent>();
|
auto* proxMon = GetComponent<ProximityMonitorComponent>();
|
||||||
|
if (!proxMon) proxMon = AddComponent<ProximityMonitorComponent>(-1);
|
||||||
proxMon->SetProximityRadius(entity, name);
|
proxMon->SetProximityRadius(entity, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1636,7 +1674,7 @@ void Entity::AddLootItem(const Loot::Info& info) const {
|
|||||||
|
|
||||||
auto* const characterComponent = GetComponent<CharacterComponent>();
|
auto* const characterComponent = GetComponent<CharacterComponent>();
|
||||||
if (!characterComponent) return;
|
if (!characterComponent) return;
|
||||||
|
LOG("Player %llu has been allowed to pickup %i with id %llu", m_ObjectID, info.lot, info.id);
|
||||||
auto& droppedLoot = characterComponent->GetDroppedLoot();
|
auto& droppedLoot = characterComponent->GetDroppedLoot();
|
||||||
droppedLoot[info.id] = info;
|
droppedLoot[info.id] = info;
|
||||||
}
|
}
|
||||||
@@ -1879,7 +1917,7 @@ const NiQuaternion& Entity::GetRotation() const {
|
|||||||
return rigidBodyPhantomPhysicsComponent->GetRotation();
|
return rigidBodyPhantomPhysicsComponent->GetRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return NiQuaternionConstant::IDENTITY;
|
return QuatUtils::IDENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::SetPosition(const NiPoint3& position) {
|
void Entity::SetPosition(const NiPoint3& position) {
|
||||||
@@ -2175,7 +2213,7 @@ const NiPoint3& Entity::GetRespawnPosition() const {
|
|||||||
|
|
||||||
const NiQuaternion& Entity::GetRespawnRotation() const {
|
const NiQuaternion& Entity::GetRespawnRotation() const {
|
||||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||||
return characterComponent ? characterComponent->GetRespawnRotation() : NiQuaternionConstant::IDENTITY;
|
return characterComponent ? characterComponent->GetRespawnRotation() : QuatUtils::IDENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::SetRespawnPos(const NiPoint3& position) const {
|
void Entity::SetRespawnPos(const NiPoint3& position) const {
|
||||||
@@ -2220,6 +2258,8 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
response.Insert("objectID", std::to_string(m_ObjectID));
|
response.Insert("objectID", std::to_string(m_ObjectID));
|
||||||
response.Insert("serverInfo", true);
|
response.Insert("serverInfo", true);
|
||||||
GameMessages::GetObjectReportInfo info{};
|
GameMessages::GetObjectReportInfo info{};
|
||||||
|
info.clientID = requestInfo.clientId;
|
||||||
|
info.bVerbose = requestInfo.bVerbose;
|
||||||
info.info = response.InsertArray("data");
|
info.info = response.InsertArray("data");
|
||||||
auto& objectInfo = info.info->PushDebug("Object Details");
|
auto& objectInfo = info.info->PushDebug("Object Details");
|
||||||
auto* table = CDClientManager::GetTable<CDObjectsTable>();
|
auto* table = CDClientManager::GetTable<CDObjectsTable>();
|
||||||
@@ -2233,17 +2273,92 @@ bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
|
|
||||||
auto& componentDetails = objectInfo.PushDebug("Component Information");
|
auto& componentDetails = objectInfo.PushDebug("Component Information");
|
||||||
for (const auto [id, component] : m_Components) {
|
for (const auto [id, component] : m_Components) {
|
||||||
componentDetails.PushDebug<AMFStringValue>(StringifiedEnum::ToString(id)) = "";
|
componentDetails.PushDebug(StringifiedEnum::ToString(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& configData = objectInfo.PushDebug("Config Data");
|
auto& configData = objectInfo.PushDebug("Config Data");
|
||||||
for (const auto config : m_Settings) {
|
for (const auto config : m_Settings) {
|
||||||
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
|
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleMsg(info);
|
HandleMsg(info);
|
||||||
|
|
||||||
auto* client = Game::entityManager->GetEntity(requestInfo.clientId);
|
auto* client = Game::entityManager->GetEntity(requestInfo.clientId);
|
||||||
if (client) GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, client->GetSystemAddress());
|
if (client) GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, client->GetSystemAddress());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgDropClientLoot(GameMessages::GameMsg& msg) {
|
||||||
|
auto& dropLootMsg = static_cast<GameMessages::DropClientLoot&>(msg);
|
||||||
|
|
||||||
|
if (dropLootMsg.item != LOT_NULL && dropLootMsg.item != 0) {
|
||||||
|
Loot::Info info{
|
||||||
|
.id = dropLootMsg.lootID,
|
||||||
|
.lot = dropLootMsg.item,
|
||||||
|
.count = dropLootMsg.count,
|
||||||
|
};
|
||||||
|
AddLootItem(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dropLootMsg.item == LOT_NULL && dropLootMsg.currency != 0) {
|
||||||
|
RegisterCoinDrop(dropLootMsg.currency);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgGetFlag(GameMessages::GameMsg& msg) {
|
||||||
|
auto& flagMsg = static_cast<GameMessages::GetFlag&>(msg);
|
||||||
|
if (m_Character) flagMsg.flag = m_Character->GetPlayerFlag(flagMsg.flagID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool Entity::MsgGetFactionTokenType(GameMessages::GameMsg& msg) {
|
||||||
|
auto& tokenMsg = static_cast<GameMessages::GetFactionTokenType&>(msg);
|
||||||
|
GameMessages::GetFlag getFlagMsg{};
|
||||||
|
|
||||||
|
getFlagMsg.flagID = ePlayerFlag::ASSEMBLY_FACTION;
|
||||||
|
MsgGetFlag(getFlagMsg);
|
||||||
|
if (getFlagMsg.flag) tokenMsg.tokenType = 8318;
|
||||||
|
|
||||||
|
getFlagMsg.flagID = ePlayerFlag::SENTINEL_FACTION;
|
||||||
|
MsgGetFlag(getFlagMsg);
|
||||||
|
if (getFlagMsg.flag) tokenMsg.tokenType = 8319;
|
||||||
|
|
||||||
|
getFlagMsg.flagID = ePlayerFlag::PARADOX_FACTION;
|
||||||
|
MsgGetFlag(getFlagMsg);
|
||||||
|
if (getFlagMsg.flag) tokenMsg.tokenType = 8320;
|
||||||
|
|
||||||
|
getFlagMsg.flagID = ePlayerFlag::VENTURE_FACTION;
|
||||||
|
MsgGetFlag(getFlagMsg);
|
||||||
|
if (getFlagMsg.flag) tokenMsg.tokenType = 8321;
|
||||||
|
|
||||||
|
LOG("Returning token type %i", tokenMsg.tokenType);
|
||||||
|
return tokenMsg.tokenType != LOT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgPickupItem(GameMessages::GameMsg& msg) {
|
||||||
|
auto& pickupItemMsg = static_cast<GameMessages::PickupItem&>(msg);
|
||||||
|
if (GetObjectID() == pickupItemMsg.lootOwnerID) {
|
||||||
|
PickupItem(pickupItemMsg.lootID);
|
||||||
|
} else {
|
||||||
|
auto* const characterComponent = GetComponent<CharacterComponent>();
|
||||||
|
if (!characterComponent) return false;
|
||||||
|
auto& droppedLoot = characterComponent->GetDroppedLoot();
|
||||||
|
const auto it = droppedLoot.find(pickupItemMsg.lootID);
|
||||||
|
if (it != droppedLoot.end()) {
|
||||||
|
CDObjectsTable* objectsTable = CDClientManager::GetTable<CDObjectsTable>();
|
||||||
|
const CDObjects& object = objectsTable->GetByID(it->second.lot);
|
||||||
|
if (object.id != 0 && object.type == "Powerup") {
|
||||||
|
return false; // Let powerups be duplicated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
droppedLoot.erase(pickupItemMsg.lootID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgChildRemoved(GameMessages::GameMsg& msg) {
|
||||||
|
GetScript()->OnChildRemoved(*this, static_cast<GameMessages::ChildRemoved&>(msg));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -176,6 +176,11 @@ public:
|
|||||||
void AddComponent(eReplicaComponentType componentId, Component* component);
|
void AddComponent(eReplicaComponentType componentId, Component* component);
|
||||||
|
|
||||||
bool MsgRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
bool MsgRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
||||||
|
bool MsgDropClientLoot(GameMessages::GameMsg& msg);
|
||||||
|
bool MsgGetFlag(GameMessages::GameMsg& msg);
|
||||||
|
bool MsgGetFactionTokenType(GameMessages::GameMsg& msg);
|
||||||
|
bool MsgPickupItem(GameMessages::GameMsg& msg);
|
||||||
|
bool MsgChildRemoved(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
// This is expceted to never return nullptr, an assert checks this.
|
// This is expceted to never return nullptr, an assert checks this.
|
||||||
CppScripts::Script* const GetScript() const;
|
CppScripts::Script* const GetScript() const;
|
||||||
@@ -342,6 +347,12 @@ public:
|
|||||||
RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void RegisterMsg(auto* self, const auto handler) {
|
||||||
|
T msg;
|
||||||
|
RegisterMsg(msg.msgId, self, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The observable for player entity position updates.
|
* @brief The observable for player entity position updates.
|
||||||
*/
|
*/
|
||||||
@@ -357,7 +368,7 @@ private:
|
|||||||
std::vector<LDFBaseData*> m_NetworkSettings;
|
std::vector<LDFBaseData*> m_NetworkSettings;
|
||||||
|
|
||||||
NiPoint3 m_DefaultPosition;
|
NiPoint3 m_DefaultPosition;
|
||||||
NiQuaternion m_DefaultRotation;
|
NiQuaternion m_DefaultRotation = QuatUtils::IDENTITY;
|
||||||
float m_Scale;
|
float m_Scale;
|
||||||
|
|
||||||
Spawner* m_Spawner;
|
Spawner* m_Spawner;
|
||||||
@@ -600,5 +611,5 @@ auto Entity::GetComponents() const {
|
|||||||
|
|
||||||
template<typename... T>
|
template<typename... T>
|
||||||
auto Entity::GetComponentsMut() const {
|
auto Entity::GetComponentsMut() const {
|
||||||
return std::tuple{GetComponent<T>()...};
|
return std::tuple{ GetComponent<T>()... };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,45 @@ std::vector<LOT> EntityManager::m_GhostingExcludedLOTs = {
|
|||||||
4967
|
4967
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ParseDelimSetting(std::set<T>& setting, const std::string_view settingName, const char delim = ',') {
|
||||||
|
const auto str = Game::config->GetValue(settingName.data());
|
||||||
|
setting.clear();
|
||||||
|
for (const auto& strVal : GeneralUtils::SplitString(str, delim)) {
|
||||||
|
const auto val = GeneralUtils::TryParse<T>(strVal);
|
||||||
|
if (val) {
|
||||||
|
setting.insert(val.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityManager::ReloadConfig() {
|
||||||
|
auto hcmode = Game::config->GetValue("hardcore_mode");
|
||||||
|
m_HardcoreMode = hcmode.empty() ? false : (hcmode == "1");
|
||||||
|
auto hcUscorePercent = Game::config->GetValue("hardcore_lose_uscore_on_death_percent");
|
||||||
|
m_HardcoreLoseUscoreOnDeathPercent = hcUscorePercent.empty() ? 10 : GeneralUtils::TryParse<uint32_t>(hcUscorePercent).value_or(10);
|
||||||
|
auto hcUscoreMult = Game::config->GetValue("hardcore_uscore_enemies_multiplier");
|
||||||
|
m_HardcoreUscoreEnemiesMultiplier = hcUscoreMult.empty() ? 2 : GeneralUtils::TryParse<uint32_t>(hcUscoreMult).value_or(2);
|
||||||
|
auto hcDropInv = Game::config->GetValue("hardcore_dropinventory_on_death");
|
||||||
|
m_HardcoreDropinventoryOnDeath = hcDropInv.empty() ? false : (hcDropInv == "1");
|
||||||
|
ParseDelimSetting<LOT>(m_HardcoreExcludedItemDrops, "hardcore_excluded_item_drops");
|
||||||
|
|
||||||
|
// We don't need to save the worlds, just need to check if this one is in the list
|
||||||
|
std::set<LWOMAPID> worlds;
|
||||||
|
ParseDelimSetting<LWOMAPID>(worlds, "hardcore_uscore_reduced_worlds");
|
||||||
|
m_HardcoreUscoreReduced = worlds.contains(Game::zoneManager->GetZoneID().GetMapID());
|
||||||
|
|
||||||
|
ParseDelimSetting<LOT>(m_HardcoreUscoreReducedLots, "hardcore_uscore_reduced_lots");
|
||||||
|
ParseDelimSetting<LOT>(m_HardcoreUscoreExcludedEnemies, "hardcore_uscore_excluded_enemies");
|
||||||
|
ParseDelimSetting<LWOMAPID>(m_HardcoreDisabledWorlds, "hardcore_disabled_worlds");
|
||||||
|
|
||||||
|
auto hcXpReduction = Game::config->GetValue("hardcore_uscore_reduction");
|
||||||
|
m_HardcoreUscoreReduction = hcXpReduction.empty() ? 1.0f : GeneralUtils::TryParse<float>(hcXpReduction).value_or(1.0f);
|
||||||
|
m_HardcoreMode = GetHardcoreDisabledWorlds().contains(Game::zoneManager->GetZoneID().GetMapID()) ? false : m_HardcoreMode;
|
||||||
|
auto hcCoinKeep = Game::config->GetValue("hardcore_coin_keep");
|
||||||
|
m_HardcoreCoinKeep = hcCoinKeep.empty() ? false : GeneralUtils::TryParse<float>(hcCoinKeep).value_or(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
void EntityManager::Initialize() {
|
void EntityManager::Initialize() {
|
||||||
// Check if this zone has ghosting enabled
|
// Check if this zone has ghosting enabled
|
||||||
m_GhostingEnabled = std::find(
|
m_GhostingEnabled = std::find(
|
||||||
@@ -61,15 +100,8 @@ void EntityManager::Initialize() {
|
|||||||
) == m_GhostingExcludedZones.end();
|
) == m_GhostingExcludedZones.end();
|
||||||
|
|
||||||
// grab hardcore mode settings and load them with sane defaults
|
// grab hardcore mode settings and load them with sane defaults
|
||||||
auto hcmode = Game::config->GetValue("hardcore_mode");
|
Game::config->AddConfigHandler([]() {Game::entityManager->ReloadConfig();});
|
||||||
m_HardcoreMode = hcmode.empty() ? false : (hcmode == "1");
|
Game::entityManager->ReloadConfig();
|
||||||
auto hcUscorePercent = Game::config->GetValue("hardcore_lose_uscore_on_death_percent");
|
|
||||||
m_HardcoreLoseUscoreOnDeathPercent = hcUscorePercent.empty() ? 10 : std::stoi(hcUscorePercent);
|
|
||||||
auto hcUscoreMult = Game::config->GetValue("hardcore_uscore_enemies_multiplier");
|
|
||||||
m_HardcoreUscoreEnemiesMultiplier = hcUscoreMult.empty() ? 2 : std::stoi(hcUscoreMult);
|
|
||||||
auto hcDropInv = Game::config->GetValue("hardcore_dropinventory_on_death");
|
|
||||||
m_HardcoreDropinventoryOnDeath = hcDropInv.empty() ? false : (hcDropInv == "1");
|
|
||||||
|
|
||||||
// If cloneID is not zero, then hardcore mode is disabled
|
// If cloneID is not zero, then hardcore mode is disabled
|
||||||
// aka minigames and props
|
// aka minigames and props
|
||||||
if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
||||||
@@ -329,16 +361,24 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
LOG("Attempted to construct null entity");
|
LOG("Attempted to construct null entity");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Don't construct GM invisible entities unless it's for the GM themselves
|
||||||
|
// GMs can see other GMs if they are the same or lower level
|
||||||
|
GameMessages::GetGMInvis getGMInvisMsg;
|
||||||
|
getGMInvisMsg.Send(entity->GetObjectID());
|
||||||
|
if (getGMInvisMsg.bGMInvis && sysAddr != entity->GetSystemAddress()) {
|
||||||
|
auto* toUser = UserManager::Instance()->GetUser(sysAddr);
|
||||||
|
if (!toUser) return;
|
||||||
|
auto* constructedUser = UserManager::Instance()->GetUser(entity->GetSystemAddress());
|
||||||
|
if (!constructedUser) return;
|
||||||
|
if (toUser->GetMaxGMLevel() < constructedUser->GetMaxGMLevel()) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (entity->GetNetworkId() == 0) {
|
if (entity->GetNetworkId() == 0) {
|
||||||
uint16_t networkId;
|
uint16_t networkId;
|
||||||
|
|
||||||
if (!m_LostNetworkIds.empty()) {
|
if (!m_LostNetworkIds.empty()) {
|
||||||
networkId = m_LostNetworkIds.top();
|
networkId = m_LostNetworkIds.top();
|
||||||
m_LostNetworkIds.pop();
|
m_LostNetworkIds.pop();
|
||||||
} else {
|
} else networkId = ++m_NetworkIdCounter;
|
||||||
networkId = ++m_NetworkIdCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->SetNetworkId(networkId);
|
entity->SetNetworkId(networkId);
|
||||||
}
|
}
|
||||||
@@ -347,10 +387,8 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
if (std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity) == m_EntitiesToGhost.end()) {
|
if (std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entity) == m_EntitiesToGhost.end()) {
|
||||||
m_EntitiesToGhost.push_back(entity);
|
m_EntitiesToGhost.push_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||||
CheckGhosting(entity);
|
CheckGhosting(entity);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,14 +419,9 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
Game::server->Send(stream, sysAddr, false);
|
Game::server->Send(stream, sysAddr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity->IsPlayer()) {
|
|
||||||
if (entity->GetGMLevel() > eGameMasterLevel::CIVILIAN) {
|
|
||||||
GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, sysAddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
||||||
//ZoneControl is special:
|
//ZoneControl is special:
|
||||||
ConstructEntity(m_ZoneControlEntity, sysAddr);
|
ConstructEntity(m_ZoneControlEntity, sysAddr);
|
||||||
|
|
||||||
@@ -456,11 +489,7 @@ void EntityManager::QueueGhostUpdate(LWOOBJID playerID) {
|
|||||||
void EntityManager::UpdateGhosting() {
|
void EntityManager::UpdateGhosting() {
|
||||||
for (const auto playerID : m_PlayersToUpdateGhosting) {
|
for (const auto playerID : m_PlayersToUpdateGhosting) {
|
||||||
auto* player = PlayerManager::GetPlayer(playerID);
|
auto* player = PlayerManager::GetPlayer(playerID);
|
||||||
|
if (!player) continue;
|
||||||
if (player == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateGhosting(player);
|
UpdateGhosting(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,6 +516,7 @@ void EntityManager::UpdateGhosting(Entity* player) {
|
|||||||
|
|
||||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||||
|
|
||||||
|
|
||||||
auto ghostingDistanceMax = m_GhostDistanceMaxSquared;
|
auto ghostingDistanceMax = m_GhostDistanceMaxSquared;
|
||||||
auto ghostingDistanceMin = m_GhostDistanceMinSqaured;
|
auto ghostingDistanceMin = m_GhostDistanceMinSqaured;
|
||||||
|
|
||||||
@@ -523,35 +553,25 @@ void EntityManager::UpdateGhosting(Entity* player) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::CheckGhosting(Entity* entity) {
|
void EntityManager::CheckGhosting(Entity* entity) {
|
||||||
if (entity == nullptr) {
|
if (!entity) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& referencePoint = entity->GetPosition();
|
const auto& referencePoint = entity->GetPosition();
|
||||||
|
|
||||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||||
if (!ghostComponent) continue;
|
if (!ghostComponent) continue;
|
||||||
|
|
||||||
const auto& entityPoint = ghostComponent->GetGhostReferencePoint();
|
const auto& entityPoint = ghostComponent->GetGhostReferencePoint();
|
||||||
|
|
||||||
const auto id = entity->GetObjectID();
|
const auto id = entity->GetObjectID();
|
||||||
|
|
||||||
const auto observed = ghostComponent->IsObserved(id);
|
const auto observed = ghostComponent->IsObserved(id);
|
||||||
|
|
||||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||||
|
|
||||||
if (observed && distance > m_GhostDistanceMaxSquared) {
|
if (observed && distance > m_GhostDistanceMaxSquared) {
|
||||||
ghostComponent->GhostEntity(id);
|
ghostComponent->GhostEntity(id);
|
||||||
|
|
||||||
DestructEntity(entity, player->GetSystemAddress());
|
DestructEntity(entity, player->GetSystemAddress());
|
||||||
|
|
||||||
entity->SetObservers(entity->GetObservers() - 1);
|
entity->SetObservers(entity->GetObservers() - 1);
|
||||||
} else if (!observed && m_GhostDistanceMinSqaured > distance) {
|
} else if (!observed && m_GhostDistanceMinSqaured > distance) {
|
||||||
ghostComponent->ObserveEntity(id);
|
ghostComponent->ObserveEntity(id);
|
||||||
|
|
||||||
ConstructEntity(entity, player->GetSystemAddress());
|
ConstructEntity(entity, player->GetSystemAddress());
|
||||||
|
|
||||||
entity->SetObservers(entity->GetObservers() + 1);
|
entity->SetObservers(entity->GetObservers() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,11 +75,19 @@ public:
|
|||||||
const uint32_t GetHardcoreLoseUscoreOnDeathPercent() { return m_HardcoreLoseUscoreOnDeathPercent; };
|
const uint32_t GetHardcoreLoseUscoreOnDeathPercent() { return m_HardcoreLoseUscoreOnDeathPercent; };
|
||||||
const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; };
|
const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; };
|
||||||
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
||||||
|
const std::set<LOT>& GetHardcoreExcludedItemDrops() { return m_HardcoreExcludedItemDrops; };
|
||||||
|
const float& GetHardcoreUscoreReduction() const { return m_HardcoreUscoreReduction; };
|
||||||
|
bool GetHardcoreUscoreReduced() const { return m_HardcoreUscoreReduced; };
|
||||||
|
const std::set<LOT>& GetHardcoreUscoreReducedLots() const { return m_HardcoreUscoreReducedLots; };
|
||||||
|
const std::set<LOT>& GetHardcoreUscoreExcludedEnemies() const { return m_HardcoreUscoreExcludedEnemies; };
|
||||||
|
const std::set<LWOMAPID>& GetHardcoreDisabledWorlds() const { return m_HardcoreDisabledWorlds; };
|
||||||
|
float GetHardcoreCoinKeep() const { return m_HardcoreCoinKeep; }
|
||||||
|
|
||||||
// Messaging
|
// Messaging
|
||||||
bool SendMessage(GameMessages::GameMsg& msg) const;
|
bool SendMessage(GameMessages::GameMsg& msg) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ReloadConfig();
|
||||||
void SerializeEntities();
|
void SerializeEntities();
|
||||||
void KillEntities();
|
void KillEntities();
|
||||||
void DeleteEntities();
|
void DeleteEntities();
|
||||||
@@ -112,6 +120,13 @@ private:
|
|||||||
uint32_t m_HardcoreLoseUscoreOnDeathPercent;
|
uint32_t m_HardcoreLoseUscoreOnDeathPercent;
|
||||||
bool m_HardcoreDropinventoryOnDeath;
|
bool m_HardcoreDropinventoryOnDeath;
|
||||||
uint32_t m_HardcoreUscoreEnemiesMultiplier;
|
uint32_t m_HardcoreUscoreEnemiesMultiplier;
|
||||||
|
std::set<LOT> m_HardcoreExcludedItemDrops;
|
||||||
|
float m_HardcoreUscoreReduction{};
|
||||||
|
bool m_HardcoreUscoreReduced{};
|
||||||
|
std::set<LOT> m_HardcoreUscoreReducedLots{};
|
||||||
|
std::set<LOT> m_HardcoreUscoreExcludedEnemies{};
|
||||||
|
std::set<LWOMAPID> m_HardcoreDisabledWorlds{};
|
||||||
|
float m_HardcoreCoinKeep{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ENTITYMANAGER_H
|
#endif // ENTITYMANAGER_H
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ void QueryToLdf(Leaderboard& leaderboard, const std::vector<ILeaderboard::Entry>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> FilterToNumResults(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer, const Leaderboard::InfoType infoType, const uint32_t numResults) {
|
std::vector<ILeaderboard::Entry> FilterToNumResults(const std::vector<ILeaderboard::Entry>& leaderboard, const LWOOBJID relatedPlayer, const Leaderboard::InfoType infoType, const uint32_t numResults) {
|
||||||
std::vector<ILeaderboard::Entry> toReturn;
|
std::vector<ILeaderboard::Entry> toReturn;
|
||||||
|
|
||||||
int32_t index = 0;
|
int32_t index = 0;
|
||||||
@@ -197,7 +197,7 @@ std::vector<ILeaderboard::Entry> FilterWeeklies(const std::vector<ILeaderboard::
|
|||||||
return weeklyLeaderboard;
|
return weeklyLeaderboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ILeaderboard::Entry> FilterFriends(const std::vector<ILeaderboard::Entry>& leaderboard, const uint32_t relatedPlayer) {
|
std::vector<ILeaderboard::Entry> FilterFriends(const std::vector<ILeaderboard::Entry>& leaderboard, const LWOOBJID relatedPlayer) {
|
||||||
// Filter the leaderboard to only include friends of the player
|
// Filter the leaderboard to only include friends of the player
|
||||||
auto friendOfPlayer = Database::Get()->GetFriendsList(relatedPlayer);
|
auto friendOfPlayer = Database::Get()->GetFriendsList(relatedPlayer);
|
||||||
std::vector<ILeaderboard::Entry> friendsLeaderboard;
|
std::vector<ILeaderboard::Entry> friendsLeaderboard;
|
||||||
@@ -217,7 +217,7 @@ std::vector<ILeaderboard::Entry> ProcessLeaderboard(
|
|||||||
const std::vector<ILeaderboard::Entry>& leaderboard,
|
const std::vector<ILeaderboard::Entry>& leaderboard,
|
||||||
const bool weekly,
|
const bool weekly,
|
||||||
const Leaderboard::InfoType infoType,
|
const Leaderboard::InfoType infoType,
|
||||||
const uint32_t relatedPlayer,
|
const LWOOBJID relatedPlayer,
|
||||||
const uint32_t numResults) {
|
const uint32_t numResults) {
|
||||||
std::vector<ILeaderboard::Entry> toReturn;
|
std::vector<ILeaderboard::Entry> toReturn;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,16 @@ Team::Team() {
|
|||||||
lootOption = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
lootOption = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LWOOBJID Team::GetNextLootOwner() {
|
||||||
|
lootRound++;
|
||||||
|
|
||||||
|
if (lootRound >= members.size()) {
|
||||||
|
lootRound = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return members[lootRound];
|
||||||
|
}
|
||||||
|
|
||||||
TeamManager::TeamManager() {
|
TeamManager::TeamManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
struct Team {
|
struct Team {
|
||||||
Team();
|
Team();
|
||||||
|
|
||||||
|
LWOOBJID GetNextLootOwner();
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY;
|
LWOOBJID teamID = LWOOBJID_EMPTY;
|
||||||
char lootOption = 0;
|
char lootOption = 0;
|
||||||
std::vector<LWOOBJID> members{};
|
std::vector<LWOOBJID> members{};
|
||||||
|
|||||||
@@ -7,6 +7,10 @@
|
|||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "eServerDisconnectIdentifiers.h"
|
#include "eServerDisconnectIdentifiers.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "MessageType/Chat.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
User::User(const SystemAddress& sysAddr, const std::string& username, const std::string& sessionKey) {
|
User::User(const SystemAddress& sysAddr, const std::string& username, const std::string& sessionKey) {
|
||||||
m_AccountID = 0;
|
m_AccountID = 0;
|
||||||
@@ -28,18 +32,18 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
|
|||||||
if (userInfo) {
|
if (userInfo) {
|
||||||
m_AccountID = userInfo->id;
|
m_AccountID = userInfo->id;
|
||||||
m_MaxGMLevel = userInfo->maxGmLevel;
|
m_MaxGMLevel = userInfo->maxGmLevel;
|
||||||
m_MuteExpire = 0; //res->getUInt64(3);
|
m_MuteExpire = userInfo->muteExpire;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we're loading a zone, we'll load the last used (aka current) character:
|
//If we're loading a zone, we'll load the last used (aka current) character:
|
||||||
if (Game::server->GetZoneID() != 0) {
|
if (Game::server->GetZoneID() != 0) {
|
||||||
auto characterList = Database::Get()->GetAccountCharacterIds(m_AccountID);
|
auto characterList = Database::Get()->GetAccountCharacterIds(m_AccountID);
|
||||||
if (!characterList.empty()) {
|
if (!characterList.empty()) {
|
||||||
const uint32_t lastUsedCharacterId = characterList.front();
|
const auto lastUsedCharacterId = characterList.front();
|
||||||
Character* character = new Character(lastUsedCharacterId, this);
|
Character* character = new Character(lastUsedCharacterId, this);
|
||||||
character->UpdateFromDatabase();
|
character->UpdateFromDatabase();
|
||||||
m_Characters.push_back(character);
|
m_Characters.push_back(character);
|
||||||
LOG("Loaded %i as it is the last used char", lastUsedCharacterId);
|
LOG("Loaded %llu as it is the last used char", lastUsedCharacterId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,8 +95,28 @@ Character* User::GetLastUsedChar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool User::GetIsMuted() const {
|
bool User::GetIsMuted() {
|
||||||
return m_MuteExpire == 1 || m_MuteExpire > time(NULL);
|
using namespace std::chrono;
|
||||||
|
constexpr auto refreshInterval = seconds{ 60 };
|
||||||
|
const auto now = steady_clock::now();
|
||||||
|
if (now - m_LastMuteCheck >= refreshInterval) {
|
||||||
|
m_LastMuteCheck = now;
|
||||||
|
if (const auto info = Database::Get()->GetAccountInfo(m_Username)) {
|
||||||
|
const auto expire = static_cast<time_t>(info->muteExpire);
|
||||||
|
if (expire != m_MuteExpire) {
|
||||||
|
m_MuteExpire = expire;
|
||||||
|
|
||||||
|
if (Game::chatServer && m_LoggedInCharID != 0) {
|
||||||
|
RakNet::BitStream bitStream;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::GM_MUTE);
|
||||||
|
bitStream.Write(m_LoggedInCharID);
|
||||||
|
bitStream.Write(m_MuteExpire);
|
||||||
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_MuteExpire == 1 || m_MuteExpire > std::time(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t User::GetMuteExpire() const {
|
time_t User::GetMuteExpire() const {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
#include "RakNetTypes.h"
|
#include "RakNetTypes.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ public:
|
|||||||
std::string& GetSessionKey() { return m_SessionKey; }
|
std::string& GetSessionKey() { return m_SessionKey; }
|
||||||
SystemAddress& GetSystemAddress() { return m_SystemAddress; }
|
SystemAddress& GetSystemAddress() { return m_SystemAddress; }
|
||||||
|
|
||||||
eGameMasterLevel GetMaxGMLevel() { return m_MaxGMLevel; }
|
eGameMasterLevel GetMaxGMLevel() const { return m_MaxGMLevel; }
|
||||||
uint32_t GetLastCharID() { return m_LastCharID; }
|
uint32_t GetLastCharID() { return m_LastCharID; }
|
||||||
void SetLastCharID(uint32_t newCharID) { m_LastCharID = newCharID; }
|
void SetLastCharID(uint32_t newCharID) { m_LastCharID = newCharID; }
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ public:
|
|||||||
const std::unordered_map<std::string, bool>& GetIsBestFriendMap() { return m_IsBestFriendMap; }
|
const std::unordered_map<std::string, bool>& GetIsBestFriendMap() { return m_IsBestFriendMap; }
|
||||||
void UpdateBestFriendValue(const std::string_view playerName, const bool newValue);
|
void UpdateBestFriendValue(const std::string_view playerName, const bool newValue);
|
||||||
|
|
||||||
bool GetIsMuted() const;
|
bool GetIsMuted();
|
||||||
|
|
||||||
time_t GetMuteExpire() const;
|
time_t GetMuteExpire() const;
|
||||||
void SetMuteExpire(time_t value);
|
void SetMuteExpire(time_t value);
|
||||||
@@ -72,7 +73,8 @@ private:
|
|||||||
bool m_LastChatMessageApproved = false;
|
bool m_LastChatMessageApproved = false;
|
||||||
int m_AmountOfTimesOutOfSync = 0;
|
int m_AmountOfTimesOutOfSync = 0;
|
||||||
const int m_MaxDesyncAllowed = 12;
|
const int m_MaxDesyncAllowed = 12;
|
||||||
time_t m_MuteExpire;
|
uint64_t m_MuteExpire;
|
||||||
|
std::chrono::steady_clock::time_point m_LastMuteCheck{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USER_H
|
#endif // USER_H
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "CheatDetection.h"
|
#include "CheatDetection.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
#include "eCharacterVersion.h"
|
||||||
|
|
||||||
UserManager* UserManager::m_Address = nullptr;
|
UserManager* UserManager::m_Address = nullptr;
|
||||||
|
|
||||||
@@ -91,6 +93,23 @@ void UserManager::Initialize() {
|
|||||||
StripCR(line);
|
StripCR(line);
|
||||||
m_PreapprovedNames.push_back(line);
|
m_PreapprovedNames.push_back(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize cached config values and register a handler to update them on config reload
|
||||||
|
// This avoids repeated lookups into dConfig at runtime.
|
||||||
|
if (Game::config) {
|
||||||
|
m_MuteAutoRejectNames = (Game::config->GetValue("mute_auto_reject_names") == "1");
|
||||||
|
m_MuteRestrictTrade = (Game::config->GetValue("mute_restrict_trade") == "1");
|
||||||
|
m_MuteRestrictMail = (Game::config->GetValue("mute_restrict_mail") == "1");
|
||||||
|
|
||||||
|
Game::config->AddConfigHandler([this]() {
|
||||||
|
this->m_MuteAutoRejectNames = (Game::config->GetValue("mute_auto_reject_names") == "1");
|
||||||
|
this->m_MuteRestrictTrade = (Game::config->GetValue("mute_restrict_trade") == "1");
|
||||||
|
this->m_MuteRestrictMail = (Game::config->GetValue("mute_restrict_mail") == "1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG("Warning: dConfig not initialized before UserManager. Cached config values will not be available.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserManager::~UserManager() {
|
UserManager::~UserManager() {
|
||||||
@@ -300,7 +319,9 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
inStream.Read(eyes);
|
inStream.Read(eyes);
|
||||||
inStream.Read(mouth);
|
inStream.Read(mouth);
|
||||||
|
|
||||||
const auto name = LUWStringName.GetAsString();
|
const bool autoRejectNames = this->GetMuteAutoRejectNames() && u->GetIsMuted();
|
||||||
|
|
||||||
|
const auto name = autoRejectNames ? "" : LUWStringName.GetAsString();
|
||||||
std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex);
|
std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex);
|
||||||
|
|
||||||
LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle);
|
LOT shirtLOT = FindCharShirtID(shirtColor, shirtStyle);
|
||||||
@@ -318,85 +339,88 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autoRejectNames) {
|
||||||
|
LOG("AccountID: %i is muted, forcing use of predefined name", u->GetAccountID());
|
||||||
|
}
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
LOG("AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
|
LOG("AccountID: %i is creating a character with predefined name: %s", u->GetAccountID(), predefinedName.c_str());
|
||||||
} else {
|
} else {
|
||||||
LOG("AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
|
LOG("AccountID: %i is creating a character with name: %s (temporary: %s)", u->GetAccountID(), name.c_str(), predefinedName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Now that the name is ok, we can get an objectID from Master:
|
//Now that the name is ok, we can get a persistent ObjectID:
|
||||||
ObjectIDManager::RequestPersistentID([=, this](uint32_t objectID) {
|
LWOOBJID objectID = ObjectIDManager::GetPersistentID();
|
||||||
if (Database::Get()->GetCharacterInfo(objectID)) {
|
const uint32_t maxRetries = 100;
|
||||||
LOG("Character object id unavailable, check object_id_tracker!");
|
uint32_t tries = 0;
|
||||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);
|
while (Database::Get()->GetCharacterInfo(objectID) && tries < maxRetries) {
|
||||||
return;
|
tries++;
|
||||||
}
|
LOG("Found a duplicate character %llu, getting a new objectID", objectID);
|
||||||
|
objectID = ObjectIDManager::GetPersistentID();
|
||||||
|
}
|
||||||
|
|
||||||
std::stringstream xml;
|
if (tries >= maxRetries) {
|
||||||
xml << "<obj v=\"1\">";
|
LOG("Failed to get a unique objectID for new character after %i tries, aborting char creation for account %i", maxRetries, u->GetAccountID());
|
||||||
|
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::OBJECT_ID_UNAVAILABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
xml << "<mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
std::stringstream xml;
|
||||||
xml << "\" hdc=\"0\" cd=\"" << shirtStyle << "\" lh=\"" << lh << "\" rh=\"" << rh << "\" es=\"" << eyebrows << "\" ";
|
xml << "<obj v=\"1\">";
|
||||||
xml << "ess=\"" << eyes << "\" ms=\"" << mouth << "\"/>";
|
|
||||||
|
|
||||||
xml << "<char acct=\"" << u->GetAccountID() << "\" cc=\"0\" gm=\"0\" ft=\"0\" llog=\"" << time(NULL) << "\" ";
|
xml << "<mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
||||||
xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" ";
|
xml << "\" hdc=\"0\" cd=\"" << shirtStyle << "\" lh=\"" << lh << "\" rh=\"" << rh << "\" es=\"" << eyebrows << "\" ";
|
||||||
xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\">";
|
xml << "ess=\"" << eyes << "\" ms=\"" << mouth << "\"/>";
|
||||||
xml << "<vl><l id=\"1000\" cid=\"0\"/></vl>";
|
|
||||||
|
|
||||||
xml << "</char>";
|
xml << "<char acct=\"" << u->GetAccountID() << "\" cc=\"0\" gm=\"0\" ft=\"0\" llog=\"" << time(NULL) << "\" ";
|
||||||
|
xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" ";
|
||||||
|
xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\">";
|
||||||
|
xml << "<vl><l id=\"1000\" cid=\"0\"/></vl>";
|
||||||
|
|
||||||
xml << "<dest hm=\"4\" hc=\"4\" im=\"0\" ic=\"0\" am=\"0\" ac=\"0\" d=\"0\"/>";
|
xml << "</char>";
|
||||||
|
|
||||||
xml << "<inv><bag><b t=\"0\" m=\"20\"/><b t=\"1\" m=\"40\"/><b t=\"2\" m=\"240\"/><b t=\"3\" m=\"240\"/><b t=\"14\" m=\"40\"/></bag><items><in t=\"0\">";
|
xml << "<dest hm=\"4\" hc=\"4\" im=\"0\" ic=\"0\" am=\"0\" ac=\"0\" d=\"0\"/>";
|
||||||
|
|
||||||
LWOOBJID lwoidforshirt = ObjectIDManager::GenerateRandomObjectID();
|
xml << "<inv><bag><b t=\"0\" m=\"20\"/><b t=\"1\" m=\"40\"/><b t=\"2\" m=\"240\"/><b t=\"3\" m=\"240\"/><b t=\"14\" m=\"40\"/></bag><items><in t=\"0\">";
|
||||||
LWOOBJID lwoidforpants;
|
|
||||||
|
|
||||||
do {
|
LWOOBJID lwoidforshirt = ObjectIDManager::GetPersistentID();
|
||||||
lwoidforpants = ObjectIDManager::GenerateRandomObjectID();
|
LWOOBJID lwoidforpants = ObjectIDManager::GetPersistentID();
|
||||||
} while (lwoidforpants == lwoidforshirt); //Make sure we don't have the same ID for both shirt and pants
|
|
||||||
|
|
||||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::CHARACTER);
|
xml << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::PERSISTENT);
|
xml << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
|
|
||||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
xml << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
xml << "</in></items></inv><lvl l=\"1\" cv=\"" << GeneralUtils::ToUnderlying(eCharacterVersion::UP_TO_DATE) << "\" sb=\"500\"/><flag></flag></obj>";
|
||||||
xml << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
|
||||||
|
|
||||||
xml << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
|
//Check to see if our name was pre-approved:
|
||||||
|
bool nameOk = IsNamePreapproved(name);
|
||||||
|
|
||||||
//Check to see if our name was pre-approved:
|
if (!nameOk && u->GetMaxGMLevel() > eGameMasterLevel::FORUM_MODERATOR) nameOk = true;
|
||||||
bool nameOk = IsNamePreapproved(name);
|
|
||||||
if (!nameOk && u->GetMaxGMLevel() > eGameMasterLevel::FORUM_MODERATOR) nameOk = true;
|
|
||||||
|
|
||||||
// If predefined name is invalid, change it to be their object id
|
// If predefined name is invalid, change it to be their object id
|
||||||
// that way more than one player can create characters if the predefined name files are not provided
|
// that way more than one player can create characters if the predefined name files are not provided
|
||||||
auto assignedPredefinedName = predefinedName;
|
auto assignedPredefinedName = predefinedName;
|
||||||
if (assignedPredefinedName == "INVALID") {
|
if (assignedPredefinedName == "INVALID") {
|
||||||
std::stringstream nameObjID;
|
std::stringstream nameObjID;
|
||||||
nameObjID << "minifig" << objectID;
|
nameObjID << "minifig" << objectID;
|
||||||
assignedPredefinedName = nameObjID.str();
|
assignedPredefinedName = nameObjID.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view nameToAssign = !name.empty() && nameOk ? name : assignedPredefinedName;
|
std::string_view nameToAssign = !name.empty() && nameOk ? name : assignedPredefinedName;
|
||||||
std::string pendingName = !name.empty() && !nameOk ? name : "";
|
std::string pendingName = !name.empty() && !nameOk ? name : "";
|
||||||
|
|
||||||
ICharInfo::Info info;
|
ICharInfo::Info info;
|
||||||
info.name = nameToAssign;
|
info.name = nameToAssign;
|
||||||
info.pendingName = pendingName;
|
info.pendingName = pendingName;
|
||||||
info.id = objectID;
|
info.id = objectID;
|
||||||
info.accountId = u->GetAccountID();
|
info.accountId = u->GetAccountID();
|
||||||
|
|
||||||
Database::Get()->InsertNewCharacter(info);
|
Database::Get()->InsertNewCharacter(info);
|
||||||
|
|
||||||
//Now finally insert our character xml:
|
//Now finally insert our character xml:
|
||||||
Database::Get()->InsertCharacterXml(objectID, xml.str());
|
Database::Get()->InsertCharacterXml(objectID, xml.str());
|
||||||
|
|
||||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
||||||
UserManager::RequestCharacterList(sysAddr);
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||||
@@ -409,9 +433,8 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID objectID;
|
LWOOBJID objectID;
|
||||||
inStream.Read(objectID);
|
inStream.Read(objectID);
|
||||||
uint32_t charID = static_cast<uint32_t>(objectID);
|
|
||||||
|
|
||||||
LOG("Received char delete req for ID: %llu (%u)", objectID, charID);
|
LOG("Received char delete req for ID: %llu", objectID);
|
||||||
|
|
||||||
bool hasCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
bool hasCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
||||||
objectID,
|
objectID,
|
||||||
@@ -423,8 +446,8 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
if (!hasCharacter) {
|
if (!hasCharacter) {
|
||||||
WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
|
WorldPackets::SendCharacterDeleteResponse(sysAddr, false);
|
||||||
} else {
|
} else {
|
||||||
LOG("Deleting character %i", charID);
|
LOG("Deleting character %llu", objectID);
|
||||||
Database::Get()->DeleteCharacter(charID);
|
Database::Get()->DeleteCharacter(objectID);
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::UNEXPECTED_DISCONNECT);
|
BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::UNEXPECTED_DISCONNECT);
|
||||||
@@ -445,17 +468,15 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID objectID;
|
LWOOBJID objectID;
|
||||||
inStream.Read(objectID);
|
inStream.Read(objectID);
|
||||||
GeneralUtils::ClearBit(objectID, eObjectBits::CHARACTER);
|
|
||||||
GeneralUtils::ClearBit(objectID, eObjectBits::PERSISTENT);
|
|
||||||
|
|
||||||
uint32_t charID = static_cast<uint32_t>(objectID);
|
LOG("Received char rename request for ID: %llu", objectID);
|
||||||
LOG("Received char rename request for ID: %llu (%u)", objectID, charID);
|
|
||||||
|
|
||||||
LUWString LUWStringName;
|
LUWString LUWStringName;
|
||||||
inStream.Read(LUWStringName);
|
inStream.Read(LUWStringName);
|
||||||
const auto newName = LUWStringName.GetAsString();
|
auto newName = LUWStringName.GetAsString();
|
||||||
|
|
||||||
Character* character = nullptr;
|
Character* character = nullptr;
|
||||||
|
const bool autoRejectNames = this->GetMuteAutoRejectNames() && u->GetIsMuted();
|
||||||
|
|
||||||
//Check if this user has this character:
|
//Check if this user has this character:
|
||||||
bool ownsCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
bool ownsCharacter = CheatDetection::VerifyLwoobjidIsSender(
|
||||||
@@ -466,7 +487,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
u->GetAccountID());
|
u->GetAccountID());
|
||||||
|
|
||||||
auto unusedItr = std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) {
|
auto unusedItr = std::find_if(u->GetCharacters().begin(), u->GetCharacters().end(), [&](Character* c) {
|
||||||
if (c->GetID() == charID) {
|
if (c->GetID() == objectID) {
|
||||||
character = c;
|
character = c;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -476,19 +497,36 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
if (!ownsCharacter || !character) {
|
if (!ownsCharacter || !character) {
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::UNKNOWN_ERROR);
|
||||||
} else if (ownsCharacter && character) {
|
} else if (ownsCharacter && character) {
|
||||||
|
if (autoRejectNames) {
|
||||||
|
// Create a random preapproved name (fallback to default if none available)
|
||||||
|
if (!m_FirstNames.empty() && !m_MiddleNames.empty() && !m_LastNames.empty()) {
|
||||||
|
std::string firstName = GeneralUtils::GetRandomElement(m_FirstNames);
|
||||||
|
std::string middleName = GeneralUtils::GetRandomElement(m_MiddleNames);
|
||||||
|
std::string lastName = GeneralUtils::GetRandomElement(m_LastNames);
|
||||||
|
newName = firstName + middleName + lastName;
|
||||||
|
} else {
|
||||||
|
newName = "character" + std::to_string(objectID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newName == character->GetName()) {
|
if (newName == character->GetName()) {
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::NAME_UNAVAILABLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Database::Get()->GetCharacterInfo(newName)) {
|
if (!Database::Get()->GetCharacterInfo(newName)) {
|
||||||
if (IsNamePreapproved(newName)) {
|
if (autoRejectNames) {
|
||||||
Database::Get()->SetCharacterName(charID, newName);
|
Database::Get()->SetCharacterName(objectID, newName);
|
||||||
|
LOG("Character %s auto-renamed to preapproved name %s due to mute", character->GetName().c_str(), newName.c_str());
|
||||||
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
|
||||||
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
|
} else if (IsNamePreapproved(newName)) {
|
||||||
|
Database::Get()->SetCharacterName(objectID, newName);
|
||||||
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
|
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
|
||||||
UserManager::RequestCharacterList(sysAddr);
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
} else {
|
} else {
|
||||||
Database::Get()->SetPendingCharacterName(charID, newName);
|
Database::Get()->SetPendingCharacterName(objectID, newName);
|
||||||
LOG("Character %s has been renamed to %s and is pending approval by a moderator.", character->GetName().c_str(), newName.c_str());
|
LOG("Character %s has been renamed to %s and is pending approval by a moderator.", character->GetName().c_str(), newName.c_str());
|
||||||
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
|
WorldPackets::SendCharacterRenameResponse(sysAddr, eRenameResponse::SUCCESS);
|
||||||
UserManager::RequestCharacterList(sysAddr);
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
@@ -502,7 +540,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID) {
|
void UserManager::LoginCharacter(const SystemAddress& sysAddr, LWOOBJID playerID) {
|
||||||
User* u = GetUser(sysAddr);
|
User* u = GetUser(sysAddr);
|
||||||
if (!u) {
|
if (!u) {
|
||||||
LOG("Couldn't get user to log in character");
|
LOG("Couldn't get user to log in character");
|
||||||
|
|||||||
@@ -35,12 +35,17 @@ public:
|
|||||||
void CreateCharacter(const SystemAddress& sysAddr, Packet* packet);
|
void CreateCharacter(const SystemAddress& sysAddr, Packet* packet);
|
||||||
void DeleteCharacter(const SystemAddress& sysAddr, Packet* packet);
|
void DeleteCharacter(const SystemAddress& sysAddr, Packet* packet);
|
||||||
void RenameCharacter(const SystemAddress& sysAddr, Packet* packet);
|
void RenameCharacter(const SystemAddress& sysAddr, Packet* packet);
|
||||||
void LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID);
|
void LoginCharacter(const SystemAddress& sysAddr, LWOOBJID playerID);
|
||||||
|
|
||||||
void SaveAllActiveCharacters();
|
void SaveAllActiveCharacters();
|
||||||
|
|
||||||
size_t GetUserCount() const { return m_Users.size(); }
|
size_t GetUserCount() const { return m_Users.size(); }
|
||||||
|
|
||||||
|
// Access cached config values
|
||||||
|
bool GetMuteAutoRejectNames() const { return m_MuteAutoRejectNames; }
|
||||||
|
bool GetMuteRestrictTrade() const { return m_MuteRestrictTrade; }
|
||||||
|
bool GetMuteRestrictMail() const { return m_MuteRestrictMail; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static UserManager* m_Address; //Singleton
|
static UserManager* m_Address; //Singleton
|
||||||
std::map<SystemAddress, User*> m_Users;
|
std::map<SystemAddress, User*> m_Users;
|
||||||
@@ -50,6 +55,11 @@ private:
|
|||||||
std::vector<std::string> m_MiddleNames;
|
std::vector<std::string> m_MiddleNames;
|
||||||
std::vector<std::string> m_LastNames;
|
std::vector<std::string> m_LastNames;
|
||||||
std::vector<std::string> m_PreapprovedNames;
|
std::vector<std::string> m_PreapprovedNames;
|
||||||
|
|
||||||
|
// Cached config values that can change on config reload
|
||||||
|
bool m_MuteAutoRejectNames = false;
|
||||||
|
bool m_MuteRestrictTrade = false;
|
||||||
|
bool m_MuteRestrictMail = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // USERMANAGER_H
|
#endif // USERMANAGER_H
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user