mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-20 13:44:21 +00:00
Compare commits
1 Commits
issue-636
...
limit-user
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
277b415196 |
29
.github/copilot-instructions.md
vendored
29
.github/copilot-instructions.md
vendored
@@ -1,29 +0,0 @@
|
||||
# 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.
|
||||
2
.github/workflows/build-and-test.yml
vendored
2
.github/workflows/build-and-test.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ windows-2022, ubuntu-22.04, macos-15-intel ]
|
||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -126,6 +126,3 @@ docker-compose.override.yml
|
||||
# CMake scripts
|
||||
!cmake/*
|
||||
!cmake/toolchains/*
|
||||
|
||||
.mcp.json
|
||||
.claude/
|
||||
@@ -15,16 +15,10 @@ set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
|
||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
||||
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_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
|
||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||
@@ -72,11 +66,7 @@ set(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
# Disabled no-register
|
||||
# Disabled unknown pragmas because Linux doesn't understand Windows pragmas.
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
add_link_options("-Wl,-rpath,@loader_path/")
|
||||
else()
|
||||
add_link_options("-Wl,-rpath,$ORIGIN/")
|
||||
endif()
|
||||
add_link_options("-Wl,-rpath,$ORIGIN/")
|
||||
add_compile_options("-fPIC")
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0 _GLIBCXX_USE_CXX17_ABI=0)
|
||||
|
||||
@@ -316,7 +306,7 @@ add_subdirectory(dServer)
|
||||
add_subdirectory(dWeb)
|
||||
|
||||
# Create a list of common libraries shared between all binaries
|
||||
set(COMMON_LIBRARIES glm::glm "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||
|
||||
# Add platform specific common libraries
|
||||
if(UNIX)
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-15-intel",
|
||||
"name": "ci-macos-13",
|
||||
"displayName": "[Release] MacOS",
|
||||
"description": "CI workflow preset for MacOS",
|
||||
"steps": [
|
||||
|
||||
@@ -16,9 +16,7 @@ RUN --mount=type=cache,target=/app/build,id=build-cache \
|
||||
cd /app/build && \
|
||||
cmake .. && \
|
||||
make -j$(nproc --ignore 1) && \
|
||||
cp -r /app/build/* /tmp/persisted-build/ && \
|
||||
mkdir -p /tmp/persisted-build/mariadbcpp && \
|
||||
cp /app/build/thirdparty/mariadb-connector-cpp/src/mariadb_connector_cpp-build/libmariadbcpp.so /tmp/persisted-build/mariadbcpp/
|
||||
cp -r /app/build/* /tmp/persisted-build/
|
||||
|
||||
FROM debian:12 as runtime
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.12.1
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
|
||||
@@ -10,15 +10,14 @@ if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
|
||||
file(MAKE_DIRECTORY "${MARIADB_MSI_DIR}")
|
||||
file(MAKE_DIRECTORY "${MARIADB_CONNECTOR_DIR}")
|
||||
|
||||
# These values track the published Windows MSI packages used by the prebuilt path.
|
||||
# Keep the Connector/C++ package version aligned with the checked out submodule tag when possible.
|
||||
# Go to https://mariadb.com/downloads/connectors/ to find the up-to-date URL parts.
|
||||
set(MARIADB_CONNECTOR_C_VERSION "3.4.8")
|
||||
set(MARIADB_CONNECTOR_C_BUCKET "4516894")
|
||||
set(MARIADB_CONNECTOR_C_MD5 "50f6fc0c77b8d3bacbeac0126e179861")
|
||||
set(MARIADB_CONNECTOR_CPP_VERSION "1.1.7")
|
||||
set(MARIADB_CONNECTOR_CPP_BUCKET "4464908")
|
||||
set(MARIADB_CONNECTOR_CPP_MD5 "08644a7ff084b5933325cadb904796e5")
|
||||
# These values need to be updated whenever a new minor release replaces an old one
|
||||
# Go to https://mariadb.com/downloads/connectors/ to find the up-to-date URL parts
|
||||
set(MARIADB_CONNECTOR_C_VERSION "3.2.7")
|
||||
set(MARIADB_CONNECTOR_C_BUCKET "2319651")
|
||||
set(MARIADB_CONNECTOR_C_MD5 "f8636d733f1d093af9d4f22f3239f885")
|
||||
set(MARIADB_CONNECTOR_CPP_VERSION "1.0.2")
|
||||
set(MARIADB_CONNECTOR_CPP_BUCKET "2531525")
|
||||
set(MARIADB_CONNECTOR_CPP_MD5 "3034bbd6ca00a0125345f9fd1a178401")
|
||||
|
||||
set(MARIADB_CONNECTOR_C_MSI "mariadb-connector-c-${MARIADB_CONNECTOR_C_VERSION}-win64.msi")
|
||||
set(MARIADB_CONNECTOR_CPP_MSI "mariadb-connector-cpp-${MARIADB_CONNECTOR_CPP_VERSION}-win64.msi")
|
||||
@@ -80,39 +79,23 @@ else() # Build from source
|
||||
-DWITH_EXTERNAL_ZLIB=ON
|
||||
-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}
|
||||
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0\ -include\ cstdint)
|
||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
else()
|
||||
set(MARIADB_EXTRA_CMAKE_ARGS
|
||||
-DCMAKE_C_FLAGS=-w # disable zlib warnings
|
||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0\ -include\ cstdint)
|
||||
-DCMAKE_CXX_FLAGS=-D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
endif()
|
||||
|
||||
set(MARIADBCPP_BUILD_DIR "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp/src/mariadb_connector_cpp-build")
|
||||
set(MARIADBCPP_INSTALL_DIR ${PROJECT_BINARY_DIR}/prefix)
|
||||
set(MARIADBCPP_LIBRARY_DIR ${PROJECT_BINARY_DIR}/mariadbcpp)
|
||||
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_LIBRARY_DIR}/plugin)
|
||||
set(MARIADBCPP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/thirdparty/mariadb-connector-cpp)
|
||||
set(MARIADB_INCLUDE_DIR "${MARIADBCPP_SOURCE_DIR}/include")
|
||||
|
||||
if(WIN32)
|
||||
set(MARIADBCPP_LIBRARY_DIR ${PROJECT_BINARY_DIR}/mariadbcpp)
|
||||
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_LIBRARY_DIR}/plugin)
|
||||
set(MARIADB_INSTALL_COMMAND)
|
||||
else()
|
||||
set(MARIADBCPP_LIBRARY_DIR ${MARIADBCPP_BUILD_DIR})
|
||||
set(MARIADBCPP_PLUGIN_DIR ${MARIADBCPP_BUILD_DIR}/libmariadb)
|
||||
set(MARIADB_INSTALL_COMMAND INSTALL_COMMAND ${CMAKE_COMMAND} -E true)
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "4.0")
|
||||
set(MARIADB_POLICY_VERSION_ARG -DCMAKE_POLICY_VERSION_MINIMUM=3.5)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(mariadb_connector_cpp
|
||||
PREFIX "${PROJECT_BINARY_DIR}/thirdparty/mariadb-connector-cpp"
|
||||
SOURCE_DIR ${MARIADBCPP_SOURCE_DIR}
|
||||
BINARY_DIR ${MARIADBCPP_BUILD_DIR}
|
||||
INSTALL_DIR ${MARIADBCPP_INSTALL_DIR}
|
||||
CMAKE_ARGS -Wno-dev
|
||||
${MARIADB_POLICY_VERSION_ARG}
|
||||
-DWITH_UNIT_TESTS=OFF
|
||||
-DMARIADB_LINK_DYNAMIC=OFF
|
||||
-DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN}
|
||||
@@ -120,7 +103,6 @@ else() # Build from source
|
||||
-DINSTALL_LIBDIR=${MARIADBCPP_LIBRARY_DIR}
|
||||
-DINSTALL_PLUGINDIR=${MARIADBCPP_PLUGIN_DIR}
|
||||
${MARIADB_EXTRA_CMAKE_ARGS}
|
||||
${MARIADB_INSTALL_COMMAND}
|
||||
BUILD_ALWAYS true
|
||||
)
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ int main(int argc, char** argv) {
|
||||
//Create all the objects we need to run our service:
|
||||
Server::SetupLogger("AuthServer");
|
||||
if (!Game::logger) return EXIT_FAILURE;
|
||||
Game::config->LogSettings();
|
||||
|
||||
LOG("Starting Auth server...");
|
||||
LOG("Version: %s", PROJECT_VERSION);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
|
||||
|
||||
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
|
||||
target_link_libraries(dChatFilter dDatabase glm::glm)
|
||||
target_link_libraries(dChatFilter dDatabase)
|
||||
|
||||
@@ -14,6 +14,6 @@ add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}
|
||||
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer" "${PROJECT_SOURCE_DIR}/dChatFilter")
|
||||
|
||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter glm::glm)
|
||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer mongoose dWeb)
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
||||
if (!receiver.ignoredPlayers.empty()) {
|
||||
LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
|
||||
} else {
|
||||
auto ignoreList = Database::Get()->GetIgnoreList(playerId);
|
||||
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
|
||||
if (ignoreList.empty()) {
|
||||
LOG_DEBUG("Player %llu has no ignores", playerId);
|
||||
return;
|
||||
@@ -43,6 +43,7 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
||||
for (auto& ignoredPlayer : ignoreList) {
|
||||
receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
|
||||
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +114,9 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
|
||||
}
|
||||
|
||||
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
||||
Database::Get()->AddIgnore(playerId, ignoredPlayerId);
|
||||
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
|
||||
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
|
||||
|
||||
receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
|
||||
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
||||
@@ -155,7 +157,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
Database::Get()->RemoveIgnore(playerId, toRemove->playerId);
|
||||
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
|
||||
receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
|
||||
|
||||
CBITSTREAM;
|
||||
|
||||
@@ -35,6 +35,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||
FriendData fd;
|
||||
fd.isFTP = false; // not a thing in DLU
|
||||
fd.friendID = friendData.friendID;
|
||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::PERSISTENT);
|
||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
||||
|
||||
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||
@@ -160,7 +161,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
|
||||
// Set the bits
|
||||
GeneralUtils::SetBit(queryPlayerID, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(queryPlayerID, eObjectBits::PERSISTENT);
|
||||
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
|
||||
// their column in the database determines what bit gets set. When the value hits 3, they
|
||||
@@ -315,6 +318,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
||||
}
|
||||
|
||||
// Convert friendID to LWOOBJID
|
||||
GeneralUtils::SetBit(friendID, eObjectBits::PERSISTENT);
|
||||
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
||||
|
||||
Database::Get()->RemoveFriend(playerID, friendID);
|
||||
|
||||
@@ -59,7 +59,6 @@ int main(int argc, char** argv) {
|
||||
//Create all the objects we need to run our service:
|
||||
Server::SetupLogger("ChatServer");
|
||||
if (!Game::logger) return EXIT_FAILURE;
|
||||
Game::config->LogSettings();
|
||||
|
||||
//Read our config:
|
||||
|
||||
@@ -202,11 +201,8 @@ int main(int argc, char** argv) {
|
||||
//Delete our objects here:
|
||||
Database::Destroy("ChatServer");
|
||||
delete Game::server;
|
||||
Game::server = nullptr;
|
||||
delete Game::logger;
|
||||
Game::logger = nullptr;
|
||||
delete Game::config;
|
||||
Game::config = nullptr;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ TeamData* TeamContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
|
||||
}
|
||||
}
|
||||
|
||||
newTeam->lootFlag = 0;
|
||||
newTeam->lootFlag = 1;
|
||||
|
||||
TeamStatusUpdate(newTeam);
|
||||
|
||||
|
||||
@@ -374,21 +374,6 @@ public:
|
||||
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:
|
||||
/**
|
||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||
|
||||
@@ -54,8 +54,6 @@ elseif (WIN32)
|
||||
zlib
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
# Disable warning about no project version.
|
||||
@@ -76,6 +74,5 @@ else ()
|
||||
endif ()
|
||||
|
||||
target_link_libraries(dCommon
|
||||
PUBLIC glm::glm
|
||||
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
|
||||
INTERFACE dDatabase)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// C++
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -19,9 +19,6 @@
|
||||
#include "dPlatforms.h"
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
#include "DluAssert.h"
|
||||
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
|
||||
enum eInventoryType : uint32_t;
|
||||
enum class eObjectBits : size_t;
|
||||
@@ -247,7 +244,7 @@ namespace GeneralUtils {
|
||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] std::optional<T> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||
const auto x = TryParse<float>(strX);
|
||||
if (!x) return std::nullopt;
|
||||
|
||||
@@ -255,7 +252,7 @@ namespace GeneralUtils {
|
||||
if (!y) return std::nullopt;
|
||||
|
||||
const auto z = TryParse<float>(strZ);
|
||||
return z ? std::make_optional<T>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||
return z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,8 +261,8 @@ namespace GeneralUtils {
|
||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] std::optional<T> TryParse(const std::span<const std::string> str) {
|
||||
return (str.size() == 3) ? TryParse<T>(str[0], str[1], str[2]) : std::nullopt;
|
||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
|
||||
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -306,7 +303,7 @@ namespace GeneralUtils {
|
||||
template<typename Container>
|
||||
inline Container::value_type GetRandomElement(const Container& container) {
|
||||
DluAssert(!container.empty());
|
||||
return container[GenerateRandomNumber<typename Container::size_type>(0, container.size() - 1)];
|
||||
return container[GenerateRandomNumber<typename Container::value_type>(0, container.size() - 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,18 +354,4 @@ namespace GeneralUtils {
|
||||
return value - modulo;
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns the current UTC date as a string in "YYYY-MM-DD" format
|
||||
inline std::string GetCurrentUTCDate() {
|
||||
const auto now = std::time(nullptr);
|
||||
std::tm utcTime{};
|
||||
#ifdef _MSC_VER
|
||||
gmtime_s(&utcTime, &now);
|
||||
#else
|
||||
gmtime_r(&now, &utcTime);
|
||||
#endif
|
||||
char buf[11];
|
||||
std::strftime(buf, sizeof(buf), "%Y-%m-%d", &utcTime);
|
||||
return std::string(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,17 +96,3 @@ bool Logger::GetLogToConsole() const {
|
||||
}
|
||||
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,19 +32,6 @@ 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_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.
|
||||
class Writer {
|
||||
public:
|
||||
|
||||
@@ -5,43 +5,13 @@
|
||||
#include "TinyXmlUtils.h"
|
||||
|
||||
#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) {
|
||||
Result toReturn;
|
||||
|
||||
// Handle empty or invalid input
|
||||
if (data.empty()) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
// Use length-based parsing to avoid expensive string copy
|
||||
const auto err = doc.Parse(data.data(), data.size());
|
||||
const auto err = doc.Parse(data.data());
|
||||
if (err != tinyxml2::XML_SUCCESS) {
|
||||
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -50,6 +20,7 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
|
||||
auto lxfml = reader["LXFML"];
|
||||
if (!lxfml) {
|
||||
LOG("Failed to find LXFML element.");
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -78,19 +49,16 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
// Calculate the lowest and highest points on the entire model
|
||||
for (const auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) continue;
|
||||
|
||||
auto xOpt = GeneralUtils::TryParse<float>(split[9]);
|
||||
auto yOpt = GeneralUtils::TryParse<float>(split[10]);
|
||||
auto zOpt = GeneralUtils::TryParse<float>(split[11]);
|
||||
|
||||
if (!xOpt.has_value() || !yOpt.has_value() || !zOpt.has_value()) continue;
|
||||
|
||||
auto x = xOpt.value();
|
||||
auto y = yOpt.value();
|
||||
auto z = zOpt.value();
|
||||
if (x < lowest.x) lowest.x = x;
|
||||
if (y < lowest.y) lowest.y = y;
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||
if (x < lowest.x) lowest.x = x;
|
||||
if (y < lowest.y) lowest.y = y;
|
||||
if (z < lowest.z) lowest.z = z;
|
||||
|
||||
if (highest.x < x) highest.x = x;
|
||||
@@ -119,19 +87,13 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
for (auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
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]);
|
||||
|
||||
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;
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x + curPosition.x;
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y + curPosition.y;
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z + curPosition.z;
|
||||
std::stringstream stream;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
stream << split[i];
|
||||
@@ -166,345 +128,3 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
toReturn.center = newRootPos;
|
||||
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,7 +6,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "NiPoint3.h"
|
||||
|
||||
@@ -19,7 +18,6 @@ namespace Lxfml {
|
||||
// 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.
|
||||
[[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.
|
||||
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
||||
|
||||
@@ -6,14 +6,10 @@
|
||||
\brief Defines a point in space in XYZ coordinates
|
||||
*/
|
||||
|
||||
|
||||
class NiPoint3;
|
||||
class NiQuaternion;
|
||||
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
|
||||
class NiPoint3 {
|
||||
public:
|
||||
@@ -25,12 +21,6 @@ public:
|
||||
//! Initializer
|
||||
constexpr NiPoint3() = default;
|
||||
|
||||
constexpr NiPoint3(const glm::vec3& vec) noexcept
|
||||
: x{ vec.x }
|
||||
, y{ vec.y }
|
||||
, z{ vec.z } {
|
||||
}
|
||||
|
||||
//! Initializer
|
||||
/*!
|
||||
\param x The x coordinate
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#endif
|
||||
|
||||
#include "NiQuaternion.h"
|
||||
#include <glm/ext/quaternion_float.hpp>
|
||||
|
||||
// MARK: Getters / Setters
|
||||
|
||||
|
||||
@@ -3,18 +3,37 @@
|
||||
// C++
|
||||
#include <cmath>
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
Vector3 QuatUtils::Euler(const NiQuaternion& quat) {
|
||||
return glm::eulerAngles(quat);
|
||||
Vector3 NiQuaternion::GetEulerAngles() const {
|
||||
Vector3 angles;
|
||||
|
||||
// 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
|
||||
|
||||
//! Look from a specific point in space to another point in space (Y-locked)
|
||||
NiQuaternion QuatUtils::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
//To make sure we don't orient around the X/Z axis:
|
||||
NiPoint3 source = sourcePoint;
|
||||
NiPoint3 dest = destPoint;
|
||||
@@ -32,11 +51,11 @@ NiQuaternion QuatUtils::LookAt(const NiPoint3& sourcePoint, const NiPoint3& dest
|
||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||
|
||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||
}
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
NiQuaternion QuatUtils::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
||||
|
||||
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
||||
@@ -48,26 +67,37 @@ NiQuaternion QuatUtils::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoin
|
||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||
|
||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||
}
|
||||
|
||||
//! Creates a Quaternion from a specific axis and angle relative to that axis
|
||||
NiQuaternion QuatUtils::AxisAngle(const Vector3& axis, float angle) {
|
||||
return glm::angleAxis(angle, glm::vec3(axis.x, axis.y, axis.z));
|
||||
NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle) {
|
||||
float halfAngle = angle * 0.5f;
|
||||
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 QuatUtils::FromEuler(const NiPoint3& eulerAngles) {
|
||||
return glm::quat(glm::vec3(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
||||
}
|
||||
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
|
||||
// Abbreviations for the various angular functions
|
||||
float cy = cos(eulerAngles.z * 0.5);
|
||||
float sy = sin(eulerAngles.z * 0.5);
|
||||
float cp = cos(eulerAngles.y * 0.5);
|
||||
float sp = sin(eulerAngles.y * 0.5);
|
||||
float cr = cos(eulerAngles.x * 0.5);
|
||||
float sr = sin(eulerAngles.x * 0.5);
|
||||
|
||||
Vector3 QuatUtils::Forward(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(0, 0, 1);
|
||||
}
|
||||
NiQuaternion q;
|
||||
q.w = cr * cp * cy + sr * sp * sy;
|
||||
q.x = sr * cp * cy - cr * sp * sy;
|
||||
q.y = cr * sp * cy + sr * cp * sy;
|
||||
q.z = cr * cp * sy - sr * sp * cy;
|
||||
|
||||
Vector3 QuatUtils::Up(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(0, 1, 0);
|
||||
}
|
||||
|
||||
Vector3 QuatUtils::Right(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(1, 0, 0);
|
||||
return q;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,158 @@
|
||||
#ifndef NIQUATERNION_H
|
||||
#define NIQUATERNION_H
|
||||
#ifndef __NIQUATERNION_H__
|
||||
#define __NIQUATERNION_H__
|
||||
|
||||
// Custom Classes
|
||||
#include "NiPoint3.h"
|
||||
|
||||
#define GLM_FORCE_QUAT_DATA_WXYZ
|
||||
/*!
|
||||
\file NiQuaternion.hpp
|
||||
\brief Defines a quaternion in space in WXYZ coordinates
|
||||
*/
|
||||
|
||||
#include <glm/ext/quaternion_float.hpp>
|
||||
class NiQuaternion;
|
||||
typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version of NiQuaternion
|
||||
|
||||
using Quaternion = glm::quat;
|
||||
using NiQuaternion = Quaternion;
|
||||
//! A class that defines a rotation in space
|
||||
class NiQuaternion {
|
||||
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 {
|
||||
constexpr NiQuaternion IDENTITY = glm::identity<NiQuaternion>();
|
||||
Vector3 Forward(const NiQuaternion& quat);
|
||||
Vector3 Up(const NiQuaternion& quat);
|
||||
Vector3 Right(const NiQuaternion& quat);
|
||||
NiQuaternion LookAt(const NiPoint3& from, const NiPoint3& to);
|
||||
NiQuaternion LookAtUnlocked(const NiPoint3& from, const NiPoint3& to);
|
||||
Vector3 Euler(const NiQuaternion& quat);
|
||||
NiQuaternion AxisAngle(const Vector3& axis, float angle);
|
||||
NiQuaternion FromEuler(const NiPoint3& eulerAngles);
|
||||
constexpr float PI_OVER_180 = glm::pi<float>() / 180.0f;
|
||||
|
||||
//! The initializer
|
||||
constexpr NiQuaternion() = default;
|
||||
|
||||
//! The initializer
|
||||
/*!
|
||||
\param w The w coordinate
|
||||
\param x The x coordinate
|
||||
\param y The y coordinate
|
||||
\param z The z coordinate
|
||||
*/
|
||||
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);
|
||||
};
|
||||
|
||||
#endif // !NIQUATERNION_H
|
||||
// Static Variables
|
||||
namespace NiQuaternionConstant {
|
||||
constexpr NiQuaternion IDENTITY(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Include constexpr and inline function definitions in a seperate file for readability
|
||||
#include "NiQuaternion.inl"
|
||||
|
||||
#endif // !__NIQUATERNION_H__
|
||||
|
||||
75
dCommon/NiQuaternion.inl
Normal file
75
dCommon/NiQuaternion.inl
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#ifndef __NIQUATERNION_H__
|
||||
#error "This should only be included inline in NiQuaternion.h: Do not include directly!"
|
||||
#endif
|
||||
|
||||
// MARK: Setters / Getters
|
||||
|
||||
//! Gets the W coordinate
|
||||
constexpr float NiQuaternion::GetW() const noexcept {
|
||||
return this->w;
|
||||
}
|
||||
|
||||
//! Sets the W coordinate
|
||||
constexpr void NiQuaternion::SetW(const float w) noexcept {
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
//! Gets the X coordinate
|
||||
constexpr float NiQuaternion::GetX() const noexcept {
|
||||
return this->x;
|
||||
}
|
||||
|
||||
//! Sets the X coordinate
|
||||
constexpr void NiQuaternion::SetX(const float x) noexcept {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
//! Gets the Y coordinate
|
||||
constexpr float NiQuaternion::GetY() const noexcept {
|
||||
return this->y;
|
||||
}
|
||||
|
||||
//! Sets the Y coordinate
|
||||
constexpr void NiQuaternion::SetY(const float y) noexcept {
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
//! Gets the Z coordinate
|
||||
constexpr float NiQuaternion::GetZ() const noexcept {
|
||||
return this->z;
|
||||
}
|
||||
|
||||
//! Sets the Z coordinate
|
||||
constexpr void NiQuaternion::SetZ(const float z) noexcept {
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Returns the forward vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetForwardVector() const noexcept {
|
||||
return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y));
|
||||
}
|
||||
|
||||
//! Returns the up vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetUpVector() const noexcept {
|
||||
return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x));
|
||||
}
|
||||
|
||||
//! Returns the right vector from the quaternion
|
||||
constexpr Vector3 NiQuaternion::GetRightVector() const noexcept {
|
||||
return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y));
|
||||
}
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
constexpr bool NiQuaternion::operator==(const NiQuaternion& rot) const noexcept {
|
||||
return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w;
|
||||
}
|
||||
|
||||
//! Operator to check for inequality
|
||||
constexpr bool NiQuaternion::operator!=(const NiQuaternion& rot) const noexcept {
|
||||
return !(*this == rot);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ struct LocalSpaceInfo {
|
||||
|
||||
struct PositionUpdate {
|
||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
||||
bool onGround = false;
|
||||
bool onRail = false;
|
||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||
|
||||
@@ -81,9 +81,6 @@ public:
|
||||
[[nodiscard]]
|
||||
AssetStream GetFile(const char* name) const;
|
||||
|
||||
[[nodiscard]]
|
||||
AssetStream GetFile(const std::string& name) const { return GetFile(name.c_str()); };
|
||||
|
||||
private:
|
||||
void LoadPackIndex();
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ void dConfig::LoadConfig() {
|
||||
void dConfig::ReloadConfig() {
|
||||
this->m_ConfigValues.clear();
|
||||
LoadConfig();
|
||||
for (const auto& handler : m_ConfigHandlers) handler();
|
||||
LogSettings();
|
||||
}
|
||||
|
||||
const std::string& dConfig::GetValue(std::string key) {
|
||||
@@ -60,18 +58,6 @@ const std::string& dConfig::GetValue(std::string 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) {
|
||||
auto splitLoc = line.find('=');
|
||||
auto key = line.substr(0, splitLoc);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
@@ -31,15 +29,10 @@ public:
|
||||
* Reloads the config file to reset values
|
||||
*/
|
||||
void ReloadConfig();
|
||||
|
||||
// Adds a function to be called when the config is (re)loaded
|
||||
void AddConfigHandler(std::function<void()> handler);
|
||||
void LogSettings() const;
|
||||
|
||||
private:
|
||||
void ProcessLine(const std::string& line);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> m_ConfigValues;
|
||||
std::vector<std::function<void()>> m_ConfigHandlers;
|
||||
std::string m_ConfigFilePath;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
namespace MessageType {
|
||||
enum class Master : uint32_t {
|
||||
REQUEST_ZONE_TRANSFER = 1,
|
||||
REQUEST_PERSISTENT_ID = 1,
|
||||
REQUEST_PERSISTENT_ID_RESPONSE,
|
||||
REQUEST_ZONE_TRANSFER,
|
||||
REQUEST_ZONE_TRANSFER_RESPONSE,
|
||||
SERVER_INFO,
|
||||
REQUEST_SESSION_KEY,
|
||||
|
||||
@@ -18,9 +18,7 @@ enum class eCharacterVersion : uint32_t {
|
||||
SPEED_BASE,
|
||||
// Fixes nexus force explorer missions
|
||||
NJ_JAYMISSIONS,
|
||||
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
|
||||
UP_TO_DATE, // will become NEXUS_FORCE_EXPLORER
|
||||
};
|
||||
|
||||
#endif //!__ECHARACTERVERSION__H__
|
||||
|
||||
@@ -50,10 +50,7 @@ enum class eMissionState : int {
|
||||
/**
|
||||
* The mission has been completed before and has now been completed again. Used for daily missions.
|
||||
*/
|
||||
COMPLETE_READY_TO_COMPLETE = 12,
|
||||
|
||||
// The mission is failed (don't know where this is used)
|
||||
FAILED = 16,
|
||||
COMPLETE_READY_TO_COMPLETE = 12
|
||||
};
|
||||
|
||||
#endif //!__MISSIONSTATE__H__
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#ifndef EOBJECTBITS_H
|
||||
#define EOBJECTBITS_H
|
||||
#ifndef __EOBJECTBITS__H__
|
||||
#define __EOBJECTBITS__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eObjectBits : size_t {
|
||||
PERSISTENT = 32,
|
||||
CLIENT = 46,
|
||||
SPAWNED = 58,
|
||||
CHARACTER = 60
|
||||
};
|
||||
|
||||
#endif //!EOBJECTBITS_H
|
||||
#endif //!__EOBJECTBITS__H__
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "CDActivitiesTable.h"
|
||||
|
||||
|
||||
void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||
// First, get the size of the table
|
||||
uint32_t size = 0;
|
||||
@@ -55,13 +56,3 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
||||
|
||||
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,7 +2,6 @@
|
||||
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
#include <optional>
|
||||
|
||||
struct CDActivities {
|
||||
uint32_t ActivityID;
|
||||
@@ -32,5 +31,4 @@ public:
|
||||
|
||||
// Queries the table with a custom "where" clause
|
||||
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/dEnums"
|
||||
)
|
||||
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3 glm::glm)
|
||||
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3)
|
||||
|
||||
if (${CDCLIENT_CACHE_ALL})
|
||||
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
add_subdirectory(CDClientDatabase)
|
||||
add_subdirectory(GameDatabase)
|
||||
|
||||
add_library(dDatabase STATIC "MigrationRunner.cpp" "ModelNormalizeMigration.cpp" "CharacterReputationMigration.cpp")
|
||||
add_library(dDatabase STATIC "MigrationRunner.cpp" "ModelNormalizeMigration.cpp")
|
||||
|
||||
add_custom_target(conncpp_dylib
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_FILE:MariaDB::ConnCpp> ${PROJECT_BINARY_DIR})
|
||||
@@ -10,5 +10,4 @@ add_dependencies(dDatabase conncpp_dylib)
|
||||
|
||||
target_include_directories(dDatabase PUBLIC ".")
|
||||
target_link_libraries(dDatabase
|
||||
PUBLIC dDatabaseCDClient dDatabaseGame
|
||||
PRIVATE glm::glm)
|
||||
PUBLIC dDatabaseCDClient dDatabaseGame)
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
#include "CharacterReputationMigration.h"
|
||||
|
||||
#include "Database.h"
|
||||
#include "Logger.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
uint32_t CharacterReputationMigration::Run() {
|
||||
uint32_t charactersMigrated = 0;
|
||||
|
||||
const auto allCharIds = Database::Get()->GetAllCharacterIds();
|
||||
const bool previousCommitValue = Database::Get()->GetAutoCommit();
|
||||
Database::Get()->SetAutoCommit(false);
|
||||
|
||||
for (const auto charId : allCharIds) {
|
||||
const auto xmlStr = Database::Get()->GetCharacterXml(charId);
|
||||
if (xmlStr.empty()) continue;
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.Parse(xmlStr.c_str(), xmlStr.size()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG("Failed to parse XML for character %llu during reputation migration", static_cast<uint64_t>(charId));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* obj = doc.FirstChildElement("obj");
|
||||
if (!obj) continue;
|
||||
|
||||
auto* character = obj->FirstChildElement("char");
|
||||
if (!character) continue;
|
||||
|
||||
int64_t reputation = 0;
|
||||
if (character->QueryInt64Attribute("rpt", &reputation) == tinyxml2::XML_SUCCESS && reputation != 0) {
|
||||
Database::Get()->SetCharacterReputation(charId, reputation);
|
||||
charactersMigrated++;
|
||||
}
|
||||
}
|
||||
|
||||
Database::Get()->Commit();
|
||||
Database::Get()->SetAutoCommit(previousCommitValue);
|
||||
|
||||
return charactersMigrated;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace CharacterReputationMigration {
|
||||
uint32_t Run();
|
||||
};
|
||||
@@ -29,7 +29,7 @@ target_include_directories(dDatabaseGame PUBLIC "."
|
||||
|
||||
target_link_libraries(dDatabaseGame
|
||||
INTERFACE dCommon
|
||||
PRIVATE sqlite3 MariaDB::ConnCpp glm::glm)
|
||||
PRIVATE sqlite3 MariaDB::ConnCpp)
|
||||
|
||||
# Glob together all headers that need to be precompiled
|
||||
file(
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "IAccountsRewardCodes.h"
|
||||
#include "IBehaviors.h"
|
||||
#include "IUgcModularBuild.h"
|
||||
#include "ICharacterReputation.h"
|
||||
#include "IPropertyReputationContribution.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (std::exception& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
||||
@@ -40,8 +38,7 @@ class GameDatabase :
|
||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList,
|
||||
public IBehaviors, public IUgcModularBuild,
|
||||
public ICharacterReputation, public IPropertyReputationContribution {
|
||||
public IBehaviors, public IUgcModularBuild {
|
||||
public:
|
||||
virtual ~GameDatabase() = default;
|
||||
// TODO: These should be made private.
|
||||
@@ -51,7 +48,7 @@ public:
|
||||
virtual void Commit() = 0;
|
||||
virtual bool GetAutoCommit() = 0;
|
||||
virtual void SetAutoCommit(bool value) = 0;
|
||||
virtual void DeleteCharacter(const LWOOBJID characterId) = 0;
|
||||
virtual void DeleteCharacter(const uint32_t characterId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__GAMEDATABASE__H__
|
||||
|
||||
@@ -14,7 +14,6 @@ public:
|
||||
std::string bcryptPassword;
|
||||
uint32_t id{};
|
||||
uint32_t playKeyId{};
|
||||
uint64_t muteExpire{};
|
||||
bool banned{};
|
||||
bool locked{};
|
||||
eGameMasterLevel maxGmLevel{};
|
||||
|
||||
@@ -14,7 +14,7 @@ enum class eActivityType : uint32_t {
|
||||
class IActivityLog {
|
||||
public:
|
||||
// Update the activity log for the given account.
|
||||
virtual void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
||||
virtual void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IACTIVITYLOG__H__
|
||||
|
||||
@@ -9,7 +9,7 @@ class IBehaviors {
|
||||
public:
|
||||
struct Info {
|
||||
LWOOBJID behaviorId{};
|
||||
LWOOBJID characterId{};
|
||||
uint32_t characterId{};
|
||||
std::string behaviorInfo;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
std::string clientVersion;
|
||||
std::string otherPlayer;
|
||||
std::string selection;
|
||||
LWOOBJID characterId{};
|
||||
uint32_t characterId{};
|
||||
};
|
||||
|
||||
// Add a new bug report to the database.
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
struct Info {
|
||||
std::string name;
|
||||
std::string pendingName;
|
||||
LWOOBJID id{};
|
||||
uint32_t id{};
|
||||
uint32_t accountId{};
|
||||
bool needsRename{};
|
||||
LWOCLONEID cloneId{};
|
||||
@@ -25,28 +25,25 @@ public:
|
||||
virtual std::vector<std::string> GetApprovedCharacterNames() = 0;
|
||||
|
||||
// Get the character info for the given character id.
|
||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) = 0;
|
||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) = 0;
|
||||
|
||||
// Get the character info for the given character name.
|
||||
virtual std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view name) = 0;
|
||||
|
||||
// Get the character ids for the given account.
|
||||
virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0;
|
||||
|
||||
// Get all character ids.
|
||||
virtual std::vector<LWOOBJID> GetAllCharacterIds() = 0;
|
||||
virtual std::vector<uint32_t> GetAccountCharacterIds(const uint32_t accountId) = 0;
|
||||
|
||||
// Insert a new character into the database.
|
||||
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;
|
||||
|
||||
// Set the name of the given character.
|
||||
virtual void SetCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
||||
virtual void SetCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
||||
|
||||
// Set the pending name of the given character.
|
||||
virtual void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) = 0;
|
||||
virtual void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) = 0;
|
||||
|
||||
// Updates the given character ids last login to be right now.
|
||||
virtual void UpdateLastLoggedInCharacter(const LWOOBJID characterId) = 0;
|
||||
virtual void UpdateLastLoggedInCharacter(const uint32_t characterId) = 0;
|
||||
|
||||
virtual bool IsNameInUse(const std::string_view name) = 0;
|
||||
};
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
class ICharXml {
|
||||
public:
|
||||
// Get the character xml for the given character id.
|
||||
virtual std::string GetCharacterXml(const LWOOBJID charId) = 0;
|
||||
virtual std::string GetCharacterXml(const uint32_t charId) = 0;
|
||||
|
||||
// Update the character xml for the given character id.
|
||||
virtual void UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) = 0;
|
||||
virtual void UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) = 0;
|
||||
|
||||
// Insert the character xml for the given character id.
|
||||
virtual void InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) = 0;
|
||||
virtual void InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) = 0;
|
||||
};
|
||||
|
||||
#endif //!__ICHARXML__H__
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#ifndef __ICHARACTERREPUTATION__H__
|
||||
#define __ICHARACTERREPUTATION__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class ICharacterReputation {
|
||||
public:
|
||||
virtual int64_t GetCharacterReputation(const LWOOBJID charId) = 0;
|
||||
virtual void SetCharacterReputation(const LWOOBJID charId, const int64_t reputation) = 0;
|
||||
};
|
||||
|
||||
#endif //!__ICHARACTERREPUTATION__H__
|
||||
@@ -8,7 +8,7 @@ class ICommandLog {
|
||||
public:
|
||||
|
||||
// Insert a new slash command log entry.
|
||||
virtual void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) = 0;
|
||||
virtual void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) = 0;
|
||||
};
|
||||
|
||||
#endif //!__ICOMMANDLOG__H__
|
||||
|
||||
@@ -8,25 +8,25 @@
|
||||
class IFriends {
|
||||
public:
|
||||
struct BestFriendStatus {
|
||||
LWOOBJID playerCharacterId{};
|
||||
LWOOBJID friendCharacterId{};
|
||||
uint32_t playerCharacterId{};
|
||||
uint32_t friendCharacterId{};
|
||||
uint32_t bestFriendStatus{};
|
||||
};
|
||||
|
||||
// Get the friends list for the given character id.
|
||||
virtual std::vector<FriendData> GetFriendsList(const LWOOBJID charId) = 0;
|
||||
virtual std::vector<FriendData> GetFriendsList(const uint32_t charId) = 0;
|
||||
|
||||
// Get the best friend status for the given player and friend character ids.
|
||||
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||
virtual std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||
|
||||
// Set the best friend status for the given player and friend character ids.
|
||||
virtual void SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
||||
virtual void SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) = 0;
|
||||
|
||||
// Add a friend to the given character id.
|
||||
virtual void AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||
virtual void AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||
|
||||
// Remove a friend from the given character id.
|
||||
virtual void RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) = 0;
|
||||
virtual void RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IFRIENDS__H__
|
||||
|
||||
@@ -9,12 +9,12 @@ class IIgnoreList {
|
||||
public:
|
||||
struct Info {
|
||||
std::string name;
|
||||
LWOOBJID id;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
virtual std::vector<Info> GetIgnoreList(const LWOOBJID playerId) = 0;
|
||||
virtual void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
||||
virtual void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) = 0;
|
||||
virtual std::vector<Info> GetIgnoreList(const uint32_t playerId) = 0;
|
||||
virtual void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||
virtual void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IIGNORELIST__H__
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class ILeaderboard {
|
||||
public:
|
||||
|
||||
struct Entry {
|
||||
LWOOBJID charId{};
|
||||
uint32_t charId{};
|
||||
uint32_t lastPlayedTimestamp{};
|
||||
float primaryScore{};
|
||||
float secondaryScore{};
|
||||
@@ -37,12 +36,12 @@ public:
|
||||
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> GetAgsLeaderboard(const uint32_t activityId) = 0;
|
||||
virtual std::optional<Score> GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) = 0;
|
||||
virtual std::optional<Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||
|
||||
virtual void SaveScore(const LWOOBJID 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 LWOOBJID playerId, const uint32_t gameId) = 0;
|
||||
virtual void IncrementTimesPlayed(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 UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) = 0;
|
||||
virtual void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||
virtual void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__ILEADERBOARD__H__
|
||||
|
||||
@@ -16,13 +16,16 @@ public:
|
||||
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
||||
|
||||
// Get the mail for the given character id.
|
||||
virtual std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) = 0;
|
||||
virtual std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) = 0;
|
||||
|
||||
// Get the mail for the given mail id.
|
||||
virtual std::optional<MailInfo> GetMail(const uint64_t mailId) = 0;
|
||||
|
||||
// Get the number of unread mail for the given character id.
|
||||
virtual uint32_t GetUnreadMailCount(const LWOOBJID characterId) = 0;
|
||||
virtual uint32_t GetUnreadMailCount(const uint32_t characterId) = 0;
|
||||
|
||||
// Get the number of mail for a given character id.
|
||||
virtual uint32_t GetMailCount(const uint32_t characterId) = 0;
|
||||
|
||||
// Mark the given mail as read.
|
||||
virtual void MarkMailRead(const uint64_t mailId) = 0;
|
||||
|
||||
@@ -6,19 +6,14 @@
|
||||
|
||||
class IObjectIdTracker {
|
||||
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.
|
||||
virtual std::optional<uint64_t> GetCurrentPersistentId() = 0;
|
||||
virtual std::optional<uint32_t> GetCurrentPersistentId() = 0;
|
||||
|
||||
// Insert the default persistent id.
|
||||
virtual void InsertDefaultPersistentId() = 0;
|
||||
|
||||
virtual Range GetPersistentIdRange() = 0;
|
||||
// Update the persistent id.
|
||||
virtual void UpdatePersistentId(const uint32_t newId) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IOBJECTIDTRACKER__H__
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
std::string description;
|
||||
std::string rejectionReason;
|
||||
LWOOBJID id{};
|
||||
LWOOBJID ownerId{};
|
||||
uint32_t ownerId{};
|
||||
LWOCLONEID cloneId{};
|
||||
int32_t privacyOption{};
|
||||
uint32_t modApproved{};
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
uint32_t mapId{};
|
||||
std::string searchString;
|
||||
ePropertySortType sortChoice{};
|
||||
LWOOBJID playerId{};
|
||||
uint32_t playerId{};
|
||||
uint32_t numResults{};
|
||||
uint32_t startIndex{};
|
||||
uint32_t playerSort{};
|
||||
@@ -39,9 +39,6 @@ public:
|
||||
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.
|
||||
virtual std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) = 0;
|
||||
|
||||
|
||||
@@ -13,19 +13,19 @@ public:
|
||||
}
|
||||
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
NiQuaternion rotation;
|
||||
LWOOBJID id{};
|
||||
LOT lot{};
|
||||
LWOOBJID ugcId{};
|
||||
uint32_t ugcId{};
|
||||
std::array<LWOOBJID, 5> behaviors{};
|
||||
};
|
||||
|
||||
// Inserts a new UGC model into the database.
|
||||
virtual void InsertNewUgcModel(
|
||||
std::stringstream& sd0Data,
|
||||
const uint64_t blueprintId,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const LWOOBJID characterId) = 0;
|
||||
const uint32_t characterId) = 0;
|
||||
|
||||
// Get the property models for the given property id.
|
||||
virtual std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) = 0;
|
||||
@@ -45,6 +45,6 @@ public:
|
||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||
|
||||
// Gets a model by ID
|
||||
virtual std::optional<Model> GetModel(const LWOOBJID modelID) = 0;
|
||||
virtual Model GetModel(const LWOOBJID modelID) = 0;
|
||||
};
|
||||
#endif //!__IPROPERTIESCONTENTS__H__
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef __IPROPERTYREPUTATIONCONTRIBUTION__H__
|
||||
#define __IPROPERTYREPUTATIONCONTRIBUTION__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class IPropertyReputationContribution {
|
||||
public:
|
||||
struct ContributionInfo {
|
||||
LWOOBJID playerId{};
|
||||
uint32_t reputationGained{};
|
||||
};
|
||||
|
||||
// Get today's reputation contributions for a property.
|
||||
virtual std::vector<ContributionInfo> GetPropertyReputationContributions(
|
||||
const LWOOBJID propertyId, const std::string& date) = 0;
|
||||
|
||||
// Upsert a player's reputation contribution for a property on a given date.
|
||||
virtual void UpdatePropertyReputationContribution(
|
||||
const LWOOBJID propertyId, const LWOOBJID playerId,
|
||||
const std::string& date, const uint32_t reputationGained) = 0;
|
||||
|
||||
// Update the total reputation on a property.
|
||||
virtual void UpdatePropertyReputation(const LWOOBJID propertyId, const uint32_t reputation) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IPROPERTYREPUTATIONCONTRIBUTION__H__
|
||||
@@ -29,7 +29,5 @@ public:
|
||||
|
||||
// Inserts a new UGC model into the database.
|
||||
virtual void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) = 0;
|
||||
|
||||
virtual std::optional<IUgc::Model> GetUgcModel(const LWOOBJID ugcId) = 0;
|
||||
};
|
||||
#endif //!__IUGC__H__
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
class IUgcModularBuild {
|
||||
public:
|
||||
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) = 0;
|
||||
virtual void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) = 0;
|
||||
virtual void DeleteUgcBuild(const LWOOBJID bigId) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ void MySQLDatabase::SetAutoCommit(bool value) {
|
||||
con->setAutoCommit(value);
|
||||
}
|
||||
|
||||
void MySQLDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||
void MySQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||
ExecuteDelete("DELETE FROM charxml WHERE id=? LIMIT 1;", characterId);
|
||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM friends WHERE player_id=? OR friend_id=?;", characterId, characterId);
|
||||
|
||||
@@ -9,20 +9,6 @@
|
||||
typedef std::unique_ptr<sql::PreparedStatement>& UniquePreppedStmtRef;
|
||||
typedef std::unique_ptr<sql::ResultSet> UniqueResultSet;
|
||||
|
||||
// This struct is used to keep the PreparedStatement alive alongside the ResultSet, since the ResultSet will be invalidated if the PreparedStatement is destroyed.
|
||||
// Declaring the members in reverse order of usage to ensure the PreparedStatement is destroyed after the ResultSet. This is guaranteed by the C++ standard.
|
||||
struct PreparedStmtResultSet {
|
||||
std::unique_ptr<sql::PreparedStatement> m_stmt;
|
||||
std::unique_ptr<sql::ResultSet> m_resultSet;
|
||||
|
||||
PreparedStmtResultSet(sql::PreparedStatement* stmt = nullptr, sql::ResultSet* resultSet = nullptr)
|
||||
: m_stmt(stmt), m_resultSet(resultSet) {}
|
||||
|
||||
sql::ResultSet* operator->() const {
|
||||
return m_resultSet.get();
|
||||
}
|
||||
};
|
||||
|
||||
// Purposefully no definition for this to provide linker errors in the case someone tries to
|
||||
// bind a parameter to a type that isn't defined.
|
||||
template<typename ParamType>
|
||||
@@ -54,31 +40,31 @@ public:
|
||||
|
||||
std::vector<std::string> GetApprovedCharacterNames() override;
|
||||
|
||||
std::vector<FriendData> GetFriendsList(LWOOBJID charID) override;
|
||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
||||
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
||||
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||
void CreateMigrationHistoryTable() override;
|
||||
bool IsMigrationRun(const std::string_view str) override;
|
||||
void InsertMigration(const std::string_view str) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
||||
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
||||
void DeleteCharacter(const uint32_t characterId) override;
|
||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||
@@ -97,30 +83,31 @@ public:
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::stringstream& sd0Data,
|
||||
const uint64_t blueprintId,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const LWOOBJID characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
||||
const uint32_t characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
uint32_t GetMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
void ClaimMailItem(const uint64_t mailId) override;
|
||||
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) 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 SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||
std::optional<uint64_t> GetCurrentPersistentId() override;
|
||||
IObjectIdTracker::Range GetPersistentIdRange() override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) 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;
|
||||
void AddBehavior(const IBehaviors::Info& info) override;
|
||||
@@ -132,42 +119,28 @@ public:
|
||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(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;
|
||||
void SaveScore(const LWOOBJID 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 LWOOBJID playerId, const uint32_t gameId) override;
|
||||
void IncrementNumWins(const LWOOBJID 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<LWOOBJID> characterId) override;
|
||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
std::vector<LWOOBJID> GetAllCharacterIds() override;
|
||||
int64_t GetCharacterReputation(const LWOOBJID charId) override;
|
||||
void SetCharacterReputation(const LWOOBJID charId, const int64_t reputation) override;
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> GetPropertyReputationContributions(
|
||||
const LWOOBJID propertyId, const std::string& date) override;
|
||||
void UpdatePropertyReputationContribution(
|
||||
const LWOOBJID propertyId, const LWOOBJID playerId,
|
||||
const std::string& date, const uint32_t reputationGained) override;
|
||||
void UpdatePropertyReputation(const LWOOBJID propertyId, const uint32_t reputation) override;
|
||||
uint32_t GetAccountCount() override;
|
||||
bool IsNameInUse(const std::string_view name) 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;
|
||||
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
// Return type may be different depending on the query, so it is up to the caller to check the return type.
|
||||
// The first argument is the query string, and the rest are the parameters to bind to the query.
|
||||
// The return type is a PreparedStmtResultSet which keeps the PreparedStatement alive alongside the ResultSet.
|
||||
// The return type is a unique_ptr to the result set, which is deleted automatically when it goes out of scope
|
||||
template<typename... Args>
|
||||
inline PreparedStmtResultSet ExecuteSelect(const std::string& query, Args&&... args) {
|
||||
PreparedStmtResultSet toReturn;
|
||||
toReturn.m_stmt.reset(CreatePreppedStmt(query));
|
||||
SetParams(toReturn.m_stmt, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(toReturn.m_resultSet.reset(toReturn.m_stmt->executeQuery()));
|
||||
// Return the PreparedStmtResultSet, which now owns both the PreparedStatement and ResultSet via unique_ptr and will ensure they are properly cleaned up.
|
||||
return toReturn;
|
||||
inline std::unique_ptr<sql::ResultSet> ExecuteSelect(const std::string& query, Args&&... args) {
|
||||
std::unique_ptr<sql::PreparedStatement> preppedStmt(CreatePreppedStmt(query));
|
||||
SetParams(preppedStmt, std::forward<Args>(args)...);
|
||||
DLU_SQL_TRY_CATCH_RETHROW(return std::unique_ptr<sql::ResultSet>(preppedStmt->executeQuery()));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@@ -196,91 +169,91 @@ private:
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string_view param) {
|
||||
LOG_DEBUG("%s", param.data());
|
||||
// LOG("%s", param.data());
|
||||
stmt->setString(index, param.data());
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const char* param) {
|
||||
LOG_DEBUG("%s", param);
|
||||
// LOG("%s", param);
|
||||
stmt->setString(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::string param) {
|
||||
LOG_DEBUG("%s", param.c_str());
|
||||
// LOG("%s", param.c_str());
|
||||
stmt->setString(index, param.c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int8_t param) {
|
||||
LOG_DEBUG("%u", param);
|
||||
// LOG("%u", param);
|
||||
stmt->setByte(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint8_t param) {
|
||||
LOG_DEBUG("%d", param);
|
||||
// LOG("%d", param);
|
||||
stmt->setByte(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int16_t param) {
|
||||
LOG_DEBUG("%u", param);
|
||||
// LOG("%u", param);
|
||||
stmt->setShort(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint16_t param) {
|
||||
LOG_DEBUG("%d", param);
|
||||
// LOG("%d", param);
|
||||
stmt->setShort(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint32_t param) {
|
||||
LOG_DEBUG("%u", param);
|
||||
// LOG("%u", param);
|
||||
stmt->setUInt(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int32_t param) {
|
||||
LOG_DEBUG("%d", param);
|
||||
// LOG("%d", param);
|
||||
stmt->setInt(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const int64_t param) {
|
||||
LOG_DEBUG("%llu", param);
|
||||
// LOG("%llu", param);
|
||||
stmt->setInt64(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const uint64_t param) {
|
||||
LOG_DEBUG("%llu", param);
|
||||
// LOG("%llu", param);
|
||||
stmt->setUInt64(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const float param) {
|
||||
LOG_DEBUG("%f", param);
|
||||
// LOG("%f", param);
|
||||
stmt->setFloat(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const double param) {
|
||||
LOG_DEBUG("%f", param);
|
||||
// LOG("%f", param);
|
||||
stmt->setDouble(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const bool param) {
|
||||
LOG_DEBUG("%s", param ? "true" : "false");
|
||||
// LOG("%d", param);
|
||||
stmt->setBoolean(index, param);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istream* param) {
|
||||
LOG_DEBUG("Blob");
|
||||
// LOG("Blob");
|
||||
// This is the one time you will ever see me use const_cast.
|
||||
stmt->setBlob(index, const_cast<std::istream*>(param));
|
||||
}
|
||||
@@ -288,21 +261,10 @@ inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::istr
|
||||
template<>
|
||||
inline void SetParam(UniquePreppedStmtRef stmt, const int index, const std::optional<uint32_t> param) {
|
||||
if (param) {
|
||||
LOG_DEBUG("%d", param.value());
|
||||
// LOG("%d", param.value());
|
||||
stmt->setInt(index, param.value());
|
||||
} else {
|
||||
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");
|
||||
// LOG("Null");
|
||||
stmt->setNull(index, sql::DataType::SQLNULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_view username) {
|
||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level, mute_expire FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||
|
||||
if (!result->next()) {
|
||||
return std::nullopt;
|
||||
@@ -16,7 +16,6 @@ std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_v
|
||||
toReturn.banned = result->getBoolean("banned");
|
||||
toReturn.locked = result->getBoolean("locked");
|
||||
toReturn.playKeyId = result->getUInt("play_key_id");
|
||||
toReturn.muteExpire = result->getUInt64("mute_expire");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
void MySQLDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"Servers.cpp"
|
||||
"Ugc.cpp"
|
||||
"UgcModularBuild.cpp"
|
||||
"CharacterReputation.cpp"
|
||||
"PropertyReputationContribution.cpp"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ std::vector<std::string> MySQLDatabase::GetApprovedCharacterNames() {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> CharInfoFromQueryResult(PreparedStmtResultSet& stmt) {
|
||||
std::optional<ICharInfo::Info> CharInfoFromQueryResult(std::unique_ptr<sql::ResultSet> stmt) {
|
||||
if (!stmt->next()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ICharInfo::Info toReturn;
|
||||
|
||||
toReturn.id = stmt->getInt64("id");
|
||||
toReturn.id = stmt->getUInt("id");
|
||||
toReturn.name = stmt->getString("name").c_str();
|
||||
toReturn.pendingName = stmt->getString("pending_name").c_str();
|
||||
toReturn.needsRename = stmt->getBoolean("needs_rename");
|
||||
@@ -30,35 +30,25 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(PreparedStmtResultSet& st
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
||||
auto result = ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId);
|
||||
return CharInfoFromQueryResult(result);
|
||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||
return CharInfoFromQueryResult(
|
||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE id = ? LIMIT 1;", charId)
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> MySQLDatabase::GetCharacterInfo(const std::string_view name) {
|
||||
auto result = ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name);
|
||||
return CharInfoFromQueryResult(result);
|
||||
return CharInfoFromQueryResult(
|
||||
ExecuteSelect("SELECT name, pending_name, needs_rename, prop_clone_id, permission_map, id, account_id FROM charinfo WHERE name = ? LIMIT 1;", name)
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> MySQLDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
||||
std::vector<uint32_t> MySQLDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
||||
auto result = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||
|
||||
std::vector<LWOOBJID> toReturn;
|
||||
std::vector<uint32_t> toReturn;
|
||||
toReturn.reserve(result->rowsCount());
|
||||
while (result->next()) {
|
||||
toReturn.push_back(result->getInt64("id"));
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> MySQLDatabase::GetAllCharacterIds() {
|
||||
auto result = ExecuteSelect("SELECT id FROM charinfo;");
|
||||
|
||||
std::vector<LWOOBJID> toReturn;
|
||||
toReturn.reserve(result->rowsCount());
|
||||
while (result->next()) {
|
||||
toReturn.push_back(result->getInt64("id"));
|
||||
toReturn.push_back(result->getUInt("id"));
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
@@ -75,15 +65,15 @@ void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
static_cast<uint32_t>(time(NULL)));
|
||||
}
|
||||
|
||||
void MySQLDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void MySQLDatabase::SetCharacterName(const uint32_t 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);
|
||||
}
|
||||
|
||||
void MySQLDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void MySQLDatabase::SetPendingCharacterName(const uint32_t 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);
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||
void MySQLDatabase::UpdateLastLoggedInCharacter(const uint32_t 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"
|
||||
|
||||
std::string MySQLDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||
std::string MySQLDatabase::GetCharacterXml(const uint32_t charId) {
|
||||
auto result = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||
|
||||
if (!result->next()) {
|
||||
@@ -10,10 +10,10 @@ std::string MySQLDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||
return result->getString("xml_data").c_str();
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
||||
void MySQLDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||
void MySQLDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
int64_t MySQLDatabase::GetCharacterReputation(const LWOOBJID charId) {
|
||||
auto result = ExecuteSelect("SELECT reputation FROM character_reputation WHERE character_id = ? LIMIT 1;", charId);
|
||||
|
||||
if (!result->next()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result->getInt64("reputation");
|
||||
}
|
||||
|
||||
void MySQLDatabase::SetCharacterReputation(const LWOOBJID charId, const int64_t reputation) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO character_reputation (character_id, reputation) VALUES (?, ?) ON DUPLICATE KEY UPDATE reputation = ?;",
|
||||
charId, reputation, reputation);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||
void MySQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||
std::vector<FriendData> MySQLDatabase::GetFriendsList(const uint32_t charId) {
|
||||
auto friendsList = ExecuteSelect(
|
||||
R"QUERY(
|
||||
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 LWOOBJID charId) {
|
||||
|
||||
while (friendsList->next()) {
|
||||
FriendData fd;
|
||||
fd.friendID = friendsList->getUInt64("player");
|
||||
fd.friendID = friendsList->getUInt("player");
|
||||
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();
|
||||
|
||||
@@ -29,7 +29,7 @@ std::vector<FriendData> MySQLDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
auto result = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
@@ -42,14 +42,14 @@ std::optional<IFriends::BestFriendStatus> MySQLDatabase::GetBestFriendStatus(con
|
||||
}
|
||||
|
||||
IFriends::BestFriendStatus toReturn;
|
||||
toReturn.playerCharacterId = result->getUInt64("player_id");
|
||||
toReturn.friendCharacterId = result->getUInt64("friend_id");
|
||||
toReturn.playerCharacterId = result->getUInt("player_id");
|
||||
toReturn.friendCharacterId = result->getUInt("friend_id");
|
||||
toReturn.bestFriendStatus = result->getUInt("best_friend");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void MySQLDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) {
|
||||
void MySQLDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t 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;",
|
||||
bestFriendStatus,
|
||||
playerCharacterId,
|
||||
@@ -59,11 +59,11 @@ void MySQLDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const
|
||||
);
|
||||
}
|
||||
|
||||
void MySQLDatabase::AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
void MySQLDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteInsert("INSERT IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
void MySQLDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const uint32_t 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;
|
||||
|
||||
ignoreList.reserve(result->rowsCount());
|
||||
while (result->next()) {
|
||||
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getInt64("ignore_id") });
|
||||
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getUInt("ignore_id") });
|
||||
}
|
||||
|
||||
return ignoreList;
|
||||
}
|
||||
|
||||
void MySQLDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void MySQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void MySQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ std::optional<uint32_t> MySQLDatabase::GetDonationTotal(const uint32_t activityI
|
||||
return donation_total->getUInt("donation_total");
|
||||
}
|
||||
|
||||
std::vector<ILeaderboard::Entry> ProcessQuery(PreparedStmtResultSet& rows) {
|
||||
std::vector<ILeaderboard::Entry> ProcessQuery(UniqueResultSet& rows) {
|
||||
std::vector<ILeaderboard::Entry> entries;
|
||||
entries.reserve(rows->rowsCount());
|
||||
|
||||
while (rows->next()) {
|
||||
auto& entry = entries.emplace_back();
|
||||
|
||||
entry.charId = rows->getUInt64("character_id");
|
||||
entry.charId = rows->getUInt("character_id");
|
||||
entry.lastPlayedTimestamp = rows->getUInt("lp_unix");
|
||||
entry.primaryScore = rows->getFloat("primaryScore");
|
||||
entry.secondaryScore = rows->getFloat("secondaryScore");
|
||||
@@ -58,21 +58,21 @@ std::vector<ILeaderboard::Entry> MySQLDatabase::GetNsLeaderboard(const uint32_t
|
||||
return ProcessQuery(leaderboard);
|
||||
}
|
||||
|
||||
void MySQLDatabase::SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||
void MySQLDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||
ExecuteInsert("INSERT leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, character_id = ?, game_id = ?;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||
void MySQLDatabase::UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||
ExecuteInsert("UPDATE leaderboard SET primaryScore = ?, secondaryScore = ?, tertiaryScore = ?, timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
void MySQLDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) {
|
||||
ExecuteUpdate("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
}
|
||||
|
||||
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||
auto res = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
if (res->next()) {
|
||||
@@ -86,6 +86,6 @@ std::optional<ILeaderboard::Score> MySQLDatabase::GetPlayerScore(const LWOOBJID
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void MySQLDatabase::IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
void MySQLDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t 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);
|
||||
}
|
||||
|
||||
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
auto res = ExecuteSelect(
|
||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||
" FROM mail WHERE receiver_id=? limit ?;",
|
||||
@@ -61,7 +61,7 @@ std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint32_t MySQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||
uint32_t MySQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||
auto res = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||
|
||||
if (!res->next()) {
|
||||
@@ -71,6 +71,16 @@ uint32_t MySQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||
return res->getInt("number_unread");
|
||||
}
|
||||
|
||||
uint32_t MySQLDatabase::GetMailCount(const uint32_t characterId) {
|
||||
auto res = ExecuteSelect("SELECT COUNT(*) AS mail_count FROM mail WHERE receiver_id=?;", characterId);
|
||||
|
||||
if (!res->next()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res->getInt("mail_count");
|
||||
}
|
||||
|
||||
void MySQLDatabase::MarkMailRead(const uint64_t mailId) {
|
||||
ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=? LIMIT 1;", mailId);
|
||||
}
|
||||
|
||||
@@ -1,42 +1,17 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::optional<uint64_t> MySQLDatabase::GetCurrentPersistentId() {
|
||||
std::optional<uint32_t> MySQLDatabase::GetCurrentPersistentId() {
|
||||
auto result = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||
if (!result->next()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return result->getUInt64("last_object_id");
|
||||
return result->getUInt("last_object_id");
|
||||
}
|
||||
|
||||
void MySQLDatabase::InsertDefaultPersistentId() {
|
||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||
}
|
||||
|
||||
IObjectIdTracker::Range MySQLDatabase::GetPersistentIdRange() {
|
||||
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;
|
||||
void MySQLDatabase::UpdatePersistentId(const uint32_t newId) {
|
||||
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
#include "MySQLDatabase.h"
|
||||
#include "ePropertySortType.h"
|
||||
|
||||
IProperty::Info ReadPropertyInfo(PreparedStmtResultSet& 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> result;
|
||||
std::string query;
|
||||
PreparedStmtResultSet properties;
|
||||
std::unique_ptr<sql::ResultSet> properties;
|
||||
|
||||
if (params.sortChoice == SORT_TYPE_FEATURED || params.sortChoice == SORT_TYPE_FRIENDS) {
|
||||
query = R"QUERY(
|
||||
@@ -134,7 +117,19 @@ std::optional<IProperty::PropertyEntranceResult> MySQLDatabase::GetProperties(co
|
||||
|
||||
while (properties->next()) {
|
||||
if (!result) result = IProperty::PropertyEntranceResult();
|
||||
result->entries.push_back(ReadPropertyInfo(properties));
|
||||
auto& entry = result->entries.emplace_back();
|
||||
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;
|
||||
@@ -149,7 +144,21 @@ std::optional<IProperty::Info> MySQLDatabase::GetPropertyInfo(const LWOMAPID map
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return ReadPropertyInfo(propertyEntry);
|
||||
IProperty::Info toReturn;
|
||||
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) {
|
||||
@@ -186,15 +195,3 @@ void MySQLDatabase::InsertNewProperty(const IProperty::Info& info, const uint32_
|
||||
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,27 +64,26 @@ void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||
}
|
||||
|
||||
std::optional<IPropertyContents::Model> MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
||||
IPropertyContents::Model MySQLDatabase::GetModel(const LWOOBJID modelID) {
|
||||
auto result = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
||||
|
||||
std::optional<IPropertyContents::Model> model = std::nullopt;
|
||||
IPropertyContents::Model model{};
|
||||
while (result->next()) {
|
||||
model = IPropertyContents::Model{};
|
||||
model->id = result->getUInt64("id");
|
||||
model->lot = static_cast<LOT>(result->getUInt("lot"));
|
||||
model->position.x = result->getFloat("x");
|
||||
model->position.y = result->getFloat("y");
|
||||
model->position.z = result->getFloat("z");
|
||||
model->rotation.w = result->getFloat("rw");
|
||||
model->rotation.x = result->getFloat("rx");
|
||||
model->rotation.y = result->getFloat("ry");
|
||||
model->rotation.z = result->getFloat("rz");
|
||||
model->ugcId = result->getUInt64("ugc_id");
|
||||
model->behaviors[0] = result->getUInt64("behavior_1");
|
||||
model->behaviors[1] = result->getUInt64("behavior_2");
|
||||
model->behaviors[2] = result->getUInt64("behavior_3");
|
||||
model->behaviors[3] = result->getUInt64("behavior_4");
|
||||
model->behaviors[4] = result->getUInt64("behavior_5");
|
||||
model.id = result->getUInt64("id");
|
||||
model.lot = static_cast<LOT>(result->getUInt("lot"));
|
||||
model.position.x = result->getFloat("x");
|
||||
model.position.y = result->getFloat("y");
|
||||
model.position.z = result->getFloat("z");
|
||||
model.rotation.w = result->getFloat("rw");
|
||||
model.rotation.x = result->getFloat("rx");
|
||||
model.rotation.y = result->getFloat("ry");
|
||||
model.rotation.z = result->getFloat("rz");
|
||||
model.ugcId = result->getUInt64("ugc_id");
|
||||
model.behaviors[0] = result->getUInt64("behavior_1");
|
||||
model.behaviors[1] = result->getUInt64("behavior_2");
|
||||
model.behaviors[2] = result->getUInt64("behavior_3");
|
||||
model.behaviors[3] = result->getUInt64("behavior_4");
|
||||
model.behaviors[4] = result->getUInt64("behavior_5");
|
||||
}
|
||||
|
||||
return model;
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> MySQLDatabase::GetPropertyReputationContributions(
|
||||
const LWOOBJID propertyId, const std::string& date) {
|
||||
auto result = ExecuteSelect(
|
||||
"SELECT player_id, reputation_gained FROM property_reputation_contribution WHERE property_id = ? AND contribution_date = ?;",
|
||||
propertyId, date);
|
||||
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> contributions;
|
||||
while (result->next()) {
|
||||
IPropertyReputationContribution::ContributionInfo info;
|
||||
info.playerId = result->getUInt64("player_id");
|
||||
info.reputationGained = static_cast<uint32_t>(result->getUInt("reputation_gained"));
|
||||
contributions.push_back(info);
|
||||
}
|
||||
return contributions;
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdatePropertyReputationContribution(
|
||||
const LWOOBJID propertyId, const LWOOBJID playerId,
|
||||
const std::string& date, const uint32_t reputationGained) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO property_reputation_contribution (property_id, player_id, contribution_date, reputation_gained) "
|
||||
"VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE reputation_gained = ?;",
|
||||
propertyId, playerId, date, reputationGained, reputationGained);
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdatePropertyReputation(const LWOOBJID propertyId, const uint32_t reputation) {
|
||||
ExecuteUpdate("UPDATE properties SET reputation = ? WHERE id = ?;", reputation, propertyId);
|
||||
}
|
||||
@@ -1,17 +1,5 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
IUgc::Model ReadModel(PreparedStmtResultSet& 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) {
|
||||
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;",
|
||||
@@ -20,7 +8,14 @@ std::vector<IUgc::Model> MySQLDatabase::GetUgcModels(const LWOOBJID& propertyId)
|
||||
std::vector<IUgc::Model> toReturn;
|
||||
|
||||
while (result->next()) {
|
||||
toReturn.push_back(ReadModel(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");
|
||||
toReturn.push_back(std::move(model));
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
@@ -32,7 +27,14 @@ std::vector<IUgc::Model> MySQLDatabase::GetAllUgcModels() {
|
||||
std::vector<IUgc::Model> models;
|
||||
models.reserve(result->rowsCount());
|
||||
while (result->next()) {
|
||||
models.push_back(ReadModel(result));
|
||||
IUgc::Model model;
|
||||
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;
|
||||
@@ -43,10 +45,10 @@ void MySQLDatabase::RemoveUnreferencedUgcModels() {
|
||||
}
|
||||
|
||||
void MySQLDatabase::InsertNewUgcModel(
|
||||
std::stringstream& sd0Data, // cant be const sad
|
||||
const uint64_t blueprintId,
|
||||
std:: stringstream& sd0Data, // cant be const sad
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const LWOOBJID characterId) {
|
||||
const uint32_t characterId) {
|
||||
const std::istream stream(sd0Data.rdbuf());
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||
@@ -69,14 +71,3 @@ void MySQLDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::stringstrea
|
||||
const std::istream stream(lxfml.rdbuf());
|
||||
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"
|
||||
|
||||
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) {
|
||||
void MySQLDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> 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) {
|
||||
if (value) {
|
||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
||||
} else {
|
||||
if (GetAutoCommit()) con->compileStatement("BEGIN;").execDML();
|
||||
} else {
|
||||
if (!GetAutoCommit()) con->compileStatement("COMMIT;").execDML();
|
||||
}
|
||||
}
|
||||
|
||||
void SQLiteDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||
void SQLiteDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||
ExecuteDelete("DELETE FROM charxml WHERE id=?;", characterId);
|
||||
ExecuteDelete("DELETE FROM command_log WHERE character_id=?;", 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<FriendData> GetFriendsList(LWOOBJID charID) override;
|
||||
std::vector<FriendData> GetFriendsList(uint32_t charID) override;
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) override;
|
||||
void SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) override;
|
||||
void AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||
void RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) override;
|
||||
void UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||
std::optional<IFriends::BestFriendStatus> GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) override;
|
||||
void SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) override;
|
||||
void AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) override;
|
||||
void UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) override;
|
||||
void DeleteUgcModelData(const LWOOBJID& modelId) override;
|
||||
void UpdateUgcModelData(const LWOOBJID& modelId, std::stringstream& lxfml) override;
|
||||
std::vector<IUgc::Model> GetAllUgcModels() override;
|
||||
void CreateMigrationHistoryTable() override;
|
||||
bool IsMigrationRun(const std::string_view str) override;
|
||||
void InsertMigration(const std::string_view str) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const LWOOBJID charId) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const uint32_t charId) override;
|
||||
std::optional<ICharInfo::Info> GetCharacterInfo(const std::string_view charId) override;
|
||||
std::string GetCharacterXml(const LWOOBJID accountId) override;
|
||||
void UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) override;
|
||||
std::string GetCharacterXml(const uint32_t accountId) override;
|
||||
void UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) override;
|
||||
std::optional<IAccounts::Info> GetAccountInfo(const std::string_view username) override;
|
||||
void InsertNewCharacter(const ICharInfo::Info info) override;
|
||||
void InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) override;
|
||||
std::vector<LWOOBJID> GetAccountCharacterIds(LWOOBJID accountId) override;
|
||||
void DeleteCharacter(const LWOOBJID characterId) override;
|
||||
void SetCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
void SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) override;
|
||||
void UpdateLastLoggedInCharacter(const LWOOBJID characterId) override;
|
||||
void InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) override;
|
||||
std::vector<uint32_t> GetAccountCharacterIds(uint32_t accountId) override;
|
||||
void DeleteCharacter(const uint32_t characterId) override;
|
||||
void SetCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void SetPendingCharacterName(const uint32_t characterId, const std::string_view name) override;
|
||||
void UpdateLastLoggedInCharacter(const uint32_t characterId) override;
|
||||
void SetPetNameModerationStatus(const LWOOBJID& petId, const IPetNames::Info& info) override;
|
||||
std::optional<IPetNames::Info> GetPetNameInfo(const LWOOBJID& petId) override;
|
||||
std::optional<IProperty::Info> GetPropertyInfo(const LWOMAPID mapId, const LWOCLONEID cloneId) override;
|
||||
@@ -81,30 +81,31 @@ public:
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::stringstream& sd0Data,
|
||||
const uint64_t blueprintId,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const LWOOBJID characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) override;
|
||||
const uint32_t characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const LWOOBJID characterId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
uint32_t GetMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
void ClaimMailItem(const uint64_t mailId) override;
|
||||
void InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) override;
|
||||
void InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) override;
|
||||
void UpdateAccountUnmuteTime(const uint32_t accountId, const uint64_t timeToUnmute) override;
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) 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 SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||
std::optional<uint64_t> GetCurrentPersistentId() override;
|
||||
IObjectIdTracker::Range GetPersistentIdRange() override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||
void AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
void RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) override;
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const LWOOBJID playerId) override;
|
||||
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) 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;
|
||||
void AddBehavior(const IBehaviors::Info& info) override;
|
||||
@@ -116,27 +117,16 @@ public:
|
||||
std::vector<ILeaderboard::Entry> GetAscendingLeaderboard(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;
|
||||
void SaveScore(const LWOOBJID 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 LWOOBJID playerId, const uint32_t gameId) override;
|
||||
void IncrementNumWins(const LWOOBJID 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<LWOOBJID> characterId) override;
|
||||
void SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
void UpdateScore(const uint32_t playerId, const uint32_t gameId, const Score& score) override;
|
||||
std::optional<ILeaderboard::Score> GetPlayerScore(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementNumWins(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void IncrementTimesPlayed(const uint32_t playerId, const uint32_t gameId) override;
|
||||
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> characterId) override;
|
||||
void DeleteUgcBuild(const LWOOBJID bigId) override;
|
||||
std::vector<LWOOBJID> GetAllCharacterIds() override;
|
||||
int64_t GetCharacterReputation(const LWOOBJID charId) override;
|
||||
void SetCharacterReputation(const LWOOBJID charId, const int64_t reputation) override;
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> GetPropertyReputationContributions(
|
||||
const LWOOBJID propertyId, const std::string& date) override;
|
||||
void UpdatePropertyReputationContribution(
|
||||
const LWOOBJID propertyId, const LWOOBJID playerId,
|
||||
const std::string& date, const uint32_t reputationGained) override;
|
||||
void UpdatePropertyReputation(const LWOOBJID propertyId, const uint32_t reputation) override;
|
||||
uint32_t GetAccountCount() override;
|
||||
bool IsNameInUse(const std::string_view name) 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;
|
||||
IPropertyContents::Model GetModel(const LWOOBJID modelID) override;
|
||||
private:
|
||||
CppSQLite3Statement CreatePreppedStmt(const std::string& query);
|
||||
|
||||
@@ -281,15 +271,4 @@ 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
|
||||
|
||||
@@ -17,7 +17,6 @@ std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_
|
||||
toReturn.banned = result.getIntField("banned");
|
||||
toReturn.locked = result.getIntField("locked");
|
||||
toReturn.playKeyId = result.getIntField("play_key_id");
|
||||
toReturn.muteExpire = static_cast<uint64_t>(result.getInt64Field("mute_expire"));
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
void SQLiteDatabase::UpdateActivityLog(const uint32_t characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ set(DDATABASES_DATABASES_SQLITE_TABLES_SOURCES
|
||||
"Servers.cpp"
|
||||
"Ugc.cpp"
|
||||
"UgcModularBuild.cpp"
|
||||
"CharacterReputation.cpp"
|
||||
"PropertyReputationContribution.cpp"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
||||
|
||||
ICharInfo::Info toReturn;
|
||||
|
||||
toReturn.id = stmt.getInt64Field("id");
|
||||
toReturn.id = stmt.getIntField("id");
|
||||
toReturn.name = stmt.getStringField("name");
|
||||
toReturn.pendingName = stmt.getStringField("pending_name");
|
||||
toReturn.needsRename = stmt.getIntField("needs_rename");
|
||||
@@ -31,7 +31,7 @@ std::optional<ICharInfo::Info> CharInfoFromQueryResult(CppSQLite3Query stmt) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const LWOOBJID charId) {
|
||||
std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||
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
|
||||
);
|
||||
@@ -43,24 +43,12 @@ std::optional<ICharInfo::Info> SQLiteDatabase::GetCharacterInfo(const std::strin
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> SQLiteDatabase::GetAccountCharacterIds(const LWOOBJID accountId) {
|
||||
std::vector<uint32_t> SQLiteDatabase::GetAccountCharacterIds(const uint32_t accountId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 4;", accountId);
|
||||
|
||||
std::vector<LWOOBJID> toReturn;
|
||||
std::vector<uint32_t> toReturn;
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(result.getInt64Field("id"));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> SQLiteDatabase::GetAllCharacterIds() {
|
||||
auto [_, result] = ExecuteSelect("SELECT id FROM charinfo;");
|
||||
|
||||
std::vector<LWOOBJID> toReturn;
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(result.getInt64Field("id"));
|
||||
toReturn.push_back(result.getIntField("id"));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
@@ -78,15 +66,15 @@ void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
static_cast<uint32_t>(time(NULL)));
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void SQLiteDatabase::SetCharacterName(const uint32_t 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);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void SQLiteDatabase::SetPendingCharacterName(const uint32_t 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);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||
void SQLiteDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||
ExecuteUpdate("UPDATE charinfo SET last_login = ? WHERE id = ?;", static_cast<uint32_t>(time(NULL)), characterId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::string SQLiteDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||
std::string SQLiteDatabase::GetCharacterXml(const uint32_t charId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;", charId);
|
||||
|
||||
if (result.eof()) {
|
||||
@@ -10,10 +10,10 @@ std::string SQLiteDatabase::GetCharacterXml(const LWOOBJID charId) {
|
||||
return result.getStringField("xml_data");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateCharacterXml(const LWOOBJID charId, const std::string_view lxfml) {
|
||||
void SQLiteDatabase::UpdateCharacterXml(const uint32_t charId, const std::string_view lxfml) {
|
||||
ExecuteUpdate("UPDATE charxml SET xml_data = ? WHERE id = ?;", lxfml, charId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||
void SQLiteDatabase::InsertCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||
ExecuteInsert("INSERT INTO `charxml` (`id`, `xml_data`) VALUES (?,?)", characterId, lxfml);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
int64_t SQLiteDatabase::GetCharacterReputation(const LWOOBJID charId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT reputation FROM character_reputation WHERE character_id = ? LIMIT 1;", charId);
|
||||
|
||||
if (result.eof()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result.getInt64Field("reputation");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetCharacterReputation(const LWOOBJID charId, const int64_t reputation) {
|
||||
ExecuteInsert(
|
||||
"INSERT OR REPLACE INTO character_reputation (character_id, reputation) VALUES (?, ?);",
|
||||
charId, reputation);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||
void SQLiteDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||
ExecuteInsert("INSERT INTO command_log (character_id, command) VALUES (?, ?);", characterId, command);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||
std::vector<FriendData> SQLiteDatabase::GetFriendsList(const uint32_t charId) {
|
||||
auto [_, friendsList] = ExecuteSelect(
|
||||
R"QUERY(
|
||||
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 LWOOBJID charId) {
|
||||
|
||||
while (!friendsList.eof()) {
|
||||
FriendData fd;
|
||||
fd.friendID = friendsList.getInt64Field("player");
|
||||
fd.friendID = friendsList.getIntField("player");
|
||||
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");
|
||||
|
||||
@@ -29,7 +29,7 @@ std::vector<FriendData> SQLiteDatabase::GetFriendsList(const LWOOBJID charId) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
@@ -42,14 +42,14 @@ std::optional<IFriends::BestFriendStatus> SQLiteDatabase::GetBestFriendStatus(co
|
||||
}
|
||||
|
||||
IFriends::BestFriendStatus toReturn;
|
||||
toReturn.playerCharacterId = result.getInt64Field("player_id");
|
||||
toReturn.friendCharacterId = result.getInt64Field("friend_id");
|
||||
toReturn.playerCharacterId = result.getIntField("player_id");
|
||||
toReturn.friendCharacterId = result.getIntField("friend_id");
|
||||
toReturn.bestFriendStatus = result.getIntField("best_friend");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId, const uint32_t bestFriendStatus) {
|
||||
void SQLiteDatabase::SetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId, const uint32_t bestFriendStatus) {
|
||||
ExecuteUpdate("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||
bestFriendStatus,
|
||||
playerCharacterId,
|
||||
@@ -59,11 +59,11 @@ void SQLiteDatabase::SetBestFriendStatus(const LWOOBJID playerCharacterId, const
|
||||
);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::AddFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
void SQLiteDatabase::AddFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteInsert("INSERT OR IGNORE INTO friends (player_id, friend_id, best_friend) VALUES (?, ?, 0);", playerCharacterId, friendCharacterId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveFriend(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
void SQLiteDatabase::RemoveFriend(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
ExecuteDelete("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?);",
|
||||
playerCharacterId,
|
||||
friendCharacterId,
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||
std::vector<IIgnoreList::Info> SQLiteDatabase::GetIgnoreList(const uint32_t 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;
|
||||
|
||||
while (!result.eof()) {
|
||||
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), result.getInt64Field("ignore_id") });
|
||||
ignoreList.push_back(IIgnoreList::Info{ result.getStringField("name"), static_cast<uint32_t>(result.getIntField("ignore_id")) });
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
return ignoreList;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void SQLiteDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
ExecuteInsert("INSERT OR IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void SQLiteDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t 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()) {
|
||||
auto& entry = entries.emplace_back();
|
||||
|
||||
entry.charId = rows.getInt64Field("character_id");
|
||||
entry.charId = rows.getIntField("character_id");
|
||||
entry.lastPlayedTimestamp = rows.getIntField("lp_unix");
|
||||
entry.primaryScore = rows.getFloatField("primaryScore");
|
||||
entry.secondaryScore = rows.getFloatField("secondaryScore");
|
||||
@@ -58,17 +58,17 @@ std::vector<ILeaderboard::Entry> SQLiteDatabase::GetNsLeaderboard(const uint32_t
|
||||
return ProcessQuery(result);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::SaveScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||
void SQLiteDatabase::SaveScore(const uint32_t playerId, const uint32_t gameId, const Score& score) {
|
||||
ExecuteInsert("INSERT INTO leaderboard (primaryScore, secondaryScore, tertiaryScore, character_id, game_id, last_played) VALUES (?,?,?,?,?,CURRENT_TIMESTAMP) ;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdateScore(const LWOOBJID playerId, const uint32_t gameId, const Score& score) {
|
||||
void SQLiteDatabase::UpdateScore(const uint32_t 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 = ?;",
|
||||
score.primaryScore, score.secondaryScore, score.tertiaryScore, playerId, gameId);
|
||||
}
|
||||
|
||||
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const uint32_t playerId, const uint32_t gameId) {
|
||||
std::optional<ILeaderboard::Score> toReturn = std::nullopt;
|
||||
auto [_, res] = ExecuteSelect("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
if (!res.eof()) {
|
||||
@@ -82,10 +82,10 @@ std::optional<ILeaderboard::Score> SQLiteDatabase::GetPlayerScore(const LWOOBJID
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::IncrementNumWins(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
void SQLiteDatabase::IncrementNumWins(const uint32_t playerId, const uint32_t gameId) {
|
||||
ExecuteUpdate("UPDATE leaderboard SET numWins = numWins + 1, last_played = CURRENT_TIMESTAMP WHERE character_id = ? AND game_id = ?;", playerId, gameId);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::IncrementTimesPlayed(const LWOOBJID playerId, const uint32_t gameId) {
|
||||
void SQLiteDatabase::IncrementTimesPlayed(const uint32_t playerId, const uint32_t 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);
|
||||
}
|
||||
|
||||
std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||
std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
auto [_, res] = ExecuteSelect(
|
||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||
" FROM mail WHERE receiver_id=? limit ?;",
|
||||
@@ -60,7 +60,7 @@ std::optional<MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
uint32_t SQLiteDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||
uint32_t SQLiteDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS number_unread FROM mail WHERE receiver_id=? AND was_read=0;", characterId);
|
||||
|
||||
if (res.eof()) {
|
||||
@@ -70,6 +70,16 @@ uint32_t SQLiteDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||
return res.getIntField("number_unread");
|
||||
}
|
||||
|
||||
uint32_t SQLiteDatabase::GetMailCount(const uint32_t characterId) {
|
||||
auto [_, res] = ExecuteSelect("SELECT COUNT(*) AS mail_count FROM mail WHERE receiver_id=?;", characterId);
|
||||
|
||||
if (res.eof()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res.getIntField("mail_count");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::MarkMailRead(const uint64_t mailId) {
|
||||
ExecuteUpdate("UPDATE mail SET was_read=1 WHERE id=?;", mailId);
|
||||
}
|
||||
@@ -81,3 +91,4 @@ void SQLiteDatabase::ClaimMailItem(const uint64_t mailId) {
|
||||
void SQLiteDatabase::DeleteMail(const uint64_t mailId) {
|
||||
ExecuteDelete("DELETE FROM mail WHERE id=?;", mailId);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,17 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::optional<uint64_t> SQLiteDatabase::GetCurrentPersistentId() {
|
||||
std::optional<uint32_t> SQLiteDatabase::GetCurrentPersistentId() {
|
||||
auto [_, result] = ExecuteSelect("SELECT last_object_id FROM object_id_tracker");
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return result.getInt64Field("last_object_id");
|
||||
return result.getIntField("last_object_id");
|
||||
}
|
||||
|
||||
void SQLiteDatabase::InsertDefaultPersistentId() {
|
||||
ExecuteInsert("INSERT INTO object_id_tracker VALUES (1);");
|
||||
}
|
||||
|
||||
IObjectIdTracker::Range SQLiteDatabase::GetPersistentIdRange() {
|
||||
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;
|
||||
void SQLiteDatabase::UpdatePersistentId(const uint32_t newId) {
|
||||
ExecuteUpdate("UPDATE object_id_tracker SET last_object_id = ?;", newId);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
#include "SQLiteDatabase.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> result;
|
||||
std::string query;
|
||||
@@ -135,7 +118,19 @@ std::optional<IProperty::PropertyEntranceResult> SQLiteDatabase::GetProperties(c
|
||||
auto& [_, properties] = propertiesRes;
|
||||
if (!properties.eof() && !result.has_value()) result = IProperty::PropertyEntranceResult();
|
||||
while (!properties.eof()) {
|
||||
result->entries.push_back(ReadPropertyInfo(properties));
|
||||
auto& entry = result->entries.emplace_back();
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -151,7 +146,21 @@ std::optional<IProperty::Info> SQLiteDatabase::GetPropertyInfo(const LWOMAPID ma
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return ReadPropertyInfo(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;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePropertyModerationInfo(const IProperty::Info& info) {
|
||||
@@ -188,15 +197,3 @@ void SQLiteDatabase::InsertNewProperty(const IProperty::Info& info, const uint32
|
||||
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,28 +64,27 @@ void SQLiteDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||
ExecuteDelete("DELETE FROM properties_contents WHERE id = ?;", modelId);
|
||||
}
|
||||
|
||||
std::optional<IPropertyContents::Model> SQLiteDatabase::GetModel(const LWOOBJID modelID) {
|
||||
IPropertyContents::Model SQLiteDatabase::GetModel(const LWOOBJID modelID) {
|
||||
auto [_, result] = ExecuteSelect("SELECT * FROM properties_contents WHERE id = ?", modelID);
|
||||
|
||||
std::optional<IPropertyContents::Model> model = std::nullopt;
|
||||
IPropertyContents::Model model{};
|
||||
if (!result.eof()) {
|
||||
do {
|
||||
model = IPropertyContents::Model{};
|
||||
model->id = result.getInt64Field("id");
|
||||
model->lot = static_cast<LOT>(result.getIntField("lot"));
|
||||
model->position.x = result.getFloatField("x");
|
||||
model->position.y = result.getFloatField("y");
|
||||
model->position.z = result.getFloatField("z");
|
||||
model->rotation.w = result.getFloatField("rw");
|
||||
model->rotation.x = result.getFloatField("rx");
|
||||
model->rotation.y = result.getFloatField("ry");
|
||||
model->rotation.z = result.getFloatField("rz");
|
||||
model->ugcId = result.getInt64Field("ugc_id");
|
||||
model->behaviors[0] = result.getInt64Field("behavior_1");
|
||||
model->behaviors[1] = result.getInt64Field("behavior_2");
|
||||
model->behaviors[2] = result.getInt64Field("behavior_3");
|
||||
model->behaviors[3] = result.getInt64Field("behavior_4");
|
||||
model->behaviors[4] = result.getInt64Field("behavior_5");
|
||||
model.id = result.getInt64Field("id");
|
||||
model.lot = static_cast<LOT>(result.getIntField("lot"));
|
||||
model.position.x = result.getFloatField("x");
|
||||
model.position.y = result.getFloatField("y");
|
||||
model.position.z = result.getFloatField("z");
|
||||
model.rotation.w = result.getFloatField("rw");
|
||||
model.rotation.x = result.getFloatField("rx");
|
||||
model.rotation.y = result.getFloatField("ry");
|
||||
model.rotation.z = result.getFloatField("rz");
|
||||
model.ugcId = result.getInt64Field("ugc_id");
|
||||
model.behaviors[0] = result.getInt64Field("behavior_1");
|
||||
model.behaviors[1] = result.getInt64Field("behavior_2");
|
||||
model.behaviors[2] = result.getInt64Field("behavior_3");
|
||||
model.behaviors[3] = result.getInt64Field("behavior_4");
|
||||
model.behaviors[4] = result.getInt64Field("behavior_5");
|
||||
} while (result.nextRow());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> SQLiteDatabase::GetPropertyReputationContributions(
|
||||
const LWOOBJID propertyId, const std::string& date) {
|
||||
auto [_, result] = ExecuteSelect(
|
||||
"SELECT player_id, reputation_gained FROM property_reputation_contribution WHERE property_id = ? AND contribution_date = ?;",
|
||||
propertyId, date);
|
||||
|
||||
std::vector<IPropertyReputationContribution::ContributionInfo> contributions;
|
||||
while (!result.eof()) {
|
||||
IPropertyReputationContribution::ContributionInfo info;
|
||||
info.playerId = result.getInt64Field("player_id");
|
||||
info.reputationGained = static_cast<uint32_t>(result.getIntField("reputation_gained"));
|
||||
contributions.push_back(info);
|
||||
result.nextRow();
|
||||
}
|
||||
return contributions;
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePropertyReputationContribution(
|
||||
const LWOOBJID propertyId, const LWOOBJID playerId,
|
||||
const std::string& date, const uint32_t reputationGained) {
|
||||
ExecuteInsert(
|
||||
"INSERT OR REPLACE INTO property_reputation_contribution (property_id, player_id, contribution_date, reputation_gained) "
|
||||
"VALUES (?, ?, ?, ?);",
|
||||
propertyId, playerId, date, reputationGained);
|
||||
}
|
||||
|
||||
void SQLiteDatabase::UpdatePropertyReputation(const LWOOBJID propertyId, const uint32_t reputation) {
|
||||
ExecuteUpdate("UPDATE properties SET reputation = ? WHERE id = ?;", reputation, propertyId);
|
||||
}
|
||||
@@ -1,17 +1,5 @@
|
||||
#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) {
|
||||
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;",
|
||||
@@ -20,7 +8,14 @@ std::vector<IUgc::Model> SQLiteDatabase::GetUgcModels(const LWOOBJID& propertyId
|
||||
std::vector<IUgc::Model> toReturn;
|
||||
|
||||
while (!result.eof()) {
|
||||
toReturn.push_back(ReadModel(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");
|
||||
toReturn.push_back(std::move(model));
|
||||
result.nextRow();
|
||||
}
|
||||
|
||||
@@ -32,7 +27,14 @@ std::vector<IUgc::Model> SQLiteDatabase::GetAllUgcModels() {
|
||||
|
||||
std::vector<IUgc::Model> models;
|
||||
while (!result.eof()) {
|
||||
models.push_back(ReadModel(result));
|
||||
IUgc::Model model;
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -45,9 +47,9 @@ void SQLiteDatabase::RemoveUnreferencedUgcModels() {
|
||||
|
||||
void SQLiteDatabase::InsertNewUgcModel(
|
||||
std::stringstream& sd0Data, // cant be const sad
|
||||
const uint64_t blueprintId,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const LWOOBJID characterId) {
|
||||
const uint32_t characterId) {
|
||||
const std::istream stream(sd0Data.rdbuf());
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `ugc`(`id`, `account_id`, `character_id`, `is_optimized`, `lxfml`, `bake_ao`, `filename`) VALUES (?,?,?,?,?,?,?)",
|
||||
@@ -70,14 +72,3 @@ void SQLiteDatabase::UpdateUgcModelData(const LWOOBJID& modelId, std::stringstre
|
||||
const std::istream stream(lxfml.rdbuf());
|
||||
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"
|
||||
|
||||
void SQLiteDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) {
|
||||
void SQLiteDatabase::InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<uint32_t> 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 {};
|
||||
}
|
||||
|
||||
std::vector<FriendData> TestSQLDatabase::GetFriendsList(LWOOBJID charID) {
|
||||
std::vector<FriendData> TestSQLDatabase::GetFriendsList(uint32_t charID) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<IFriends::BestFriendStatus> TestSQLDatabase::GetBestFriendStatus(const LWOOBJID playerCharacterId, const LWOOBJID friendCharacterId) {
|
||||
std::optional<IFriends::BestFriendStatus> TestSQLDatabase::GetBestFriendStatus(const uint32_t playerCharacterId, const uint32_t friendCharacterId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void TestSQLDatabase::SetBestFriendStatus(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId, const uint32_t bestFriendStatus) {
|
||||
void TestSQLDatabase::SetBestFriendStatus(const uint32_t playerAccountId, const uint32_t friendAccountId, const uint32_t bestFriendStatus) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::AddFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) {
|
||||
void TestSQLDatabase::AddFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::RemoveFriend(const LWOOBJID playerAccountId, const LWOOBJID friendAccountId) {
|
||||
void TestSQLDatabase::RemoveFriend(const uint32_t playerAccountId, const uint32_t friendAccountId) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::UpdateActivityLog(const LWOOBJID characterId, const eActivityType activityType, const LWOMAPID mapId) {
|
||||
void TestSQLDatabase::UpdateActivityLog(const uint32_t 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 LWOOBJID charId) {
|
||||
std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const uint32_t charId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ std::optional<ICharInfo::Info> TestSQLDatabase::GetCharacterInfo(const std::stri
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string TestSQLDatabase::GetCharacterXml(const LWOOBJID accountId) {
|
||||
std::string TestSQLDatabase::GetCharacterXml(const uint32_t accountId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void TestSQLDatabase::UpdateCharacterXml(const LWOOBJID characterId, const std::string_view lxfml) {
|
||||
void TestSQLDatabase::UpdateCharacterXml(const uint32_t characterId, const std::string_view lxfml) {
|
||||
|
||||
}
|
||||
|
||||
@@ -104,27 +104,27 @@ void TestSQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::InsertCharacterXml(const LWOOBJID accountId, const std::string_view lxfml) {
|
||||
void TestSQLDatabase::InsertCharacterXml(const uint32_t accountId, const std::string_view lxfml) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> TestSQLDatabase::GetAccountCharacterIds(LWOOBJID accountId) {
|
||||
std::vector<uint32_t> TestSQLDatabase::GetAccountCharacterIds(uint32_t accountId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void TestSQLDatabase::DeleteCharacter(const LWOOBJID characterId) {
|
||||
void TestSQLDatabase::DeleteCharacter(const uint32_t characterId) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::SetCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void TestSQLDatabase::SetCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::SetPendingCharacterName(const LWOOBJID characterId, const std::string_view name) {
|
||||
void TestSQLDatabase::SetPendingCharacterName(const uint32_t characterId, const std::string_view name) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::UpdateLastLoggedInCharacter(const LWOOBJID characterId) {
|
||||
void TestSQLDatabase::UpdateLastLoggedInCharacter(const uint32_t characterId) {
|
||||
|
||||
}
|
||||
|
||||
@@ -192,11 +192,11 @@ void TestSQLDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::InsertNewUgcModel(std::stringstream& sd0Data, const uint64_t blueprintId, const uint32_t accountId, const LWOOBJID characterId) {
|
||||
void TestSQLDatabase::InsertNewUgcModel(std::stringstream& sd0Data, const uint32_t blueprintId, const uint32_t accountId, const uint32_t characterId) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<MailInfo> TestSQLDatabase::GetMailForPlayer(const LWOOBJID characterId, const uint32_t numberOfMail) {
|
||||
std::vector<MailInfo> TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ std::optional<MailInfo> TestSQLDatabase::GetMail(const uint64_t mailId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
uint32_t TestSQLDatabase::GetUnreadMailCount(const LWOOBJID characterId) {
|
||||
uint32_t TestSQLDatabase::GetUnreadMailCount(const uint32_t characterId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ void TestSQLDatabase::ClaimMailItem(const uint64_t mailId) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::InsertSlashCommandUsage(const LWOOBJID characterId, const std::string_view command) {
|
||||
void TestSQLDatabase::InsertSlashCommandUsage(const uint32_t characterId, const std::string_view command) {
|
||||
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ void TestSQLDatabase::SetMasterInfo(const IServers::MasterInfo& info) {
|
||||
|
||||
}
|
||||
|
||||
std::optional<uint64_t> TestSQLDatabase::GetCurrentPersistentId() {
|
||||
std::optional<uint32_t> TestSQLDatabase::GetCurrentPersistentId() {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -252,6 +252,10 @@ void TestSQLDatabase::InsertDefaultPersistentId() {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::UpdatePersistentId(const uint32_t id) {
|
||||
|
||||
}
|
||||
|
||||
std::optional<uint32_t> TestSQLDatabase::GetDonationTotal(const uint32_t activityId) {
|
||||
return {};
|
||||
}
|
||||
@@ -264,15 +268,15 @@ std::vector<IUgc::Model> TestSQLDatabase::GetUgcModels(const LWOOBJID& propertyI
|
||||
return {};
|
||||
}
|
||||
|
||||
void TestSQLDatabase::AddIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void TestSQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::RemoveIgnore(const LWOOBJID playerId, const LWOOBJID ignoredPlayerId) {
|
||||
void TestSQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<IIgnoreList::Info> TestSQLDatabase::GetIgnoreList(const LWOOBJID playerId) {
|
||||
std::vector<IIgnoreList::Info> TestSQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -300,6 +304,3 @@ void TestSQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGame
|
||||
|
||||
}
|
||||
|
||||
IObjectIdTracker::Range TestSQLDatabase::GetPersistentIdRange() {
|
||||
return {};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user