mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-21 11:59:37 -06:00
Compare commits
1 Commits
mysql-repl
...
EmosewaMC-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4353f37d00 |
@@ -14,4 +14,4 @@ EXTERNAL_IP=localhost
|
|||||||
MARIADB_USER=darkflame
|
MARIADB_USER=darkflame
|
||||||
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
MARIADB_ROOT_PASSWORD=SECRET_VALUE_CHANGE_ME
|
||||||
MARIADB_DATABASE=darkflame
|
MARIADB_DATABASE=darkflame
|
||||||
@@ -97,56 +97,15 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
|
|||||||
|
|
||||||
# Copy resource files on first build
|
# Copy resource files on first build
|
||||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||||
message(STATUS "Checking resource file integrity")
|
foreach(resource_file ${RESOURCE_FILES})
|
||||||
foreach (resource_file ${RESOURCE_FILES})
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||||
set(file_size 0)
|
|
||||||
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
|
||||||
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
|
||||||
endif()
|
|
||||||
if (${file_size} EQUAL 0)
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
message("Moved ${resource_file} to project binary directory")
|
||||||
elseif (resource_file MATCHES ".ini")
|
|
||||||
message(STATUS "Checking " ${resource_file} " for missing config options")
|
|
||||||
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
|
||||||
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
|
||||||
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
|
||||||
set(parsed_current_file_contents "")
|
|
||||||
# Remove comment lines so they do not interfere with the variable parsing
|
|
||||||
foreach (line ${current_file_contents})
|
|
||||||
string(FIND ${line} "#" is_comment)
|
|
||||||
if (NOT ${is_comment} EQUAL 0)
|
|
||||||
string(APPEND parsed_current_file_contents ${line})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
|
|
||||||
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
|
|
||||||
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
|
|
||||||
set(line_to_add "")
|
|
||||||
foreach (line ${depot_file_contents})
|
|
||||||
string(FIND ${line} "#" is_comment)
|
|
||||||
if (NOT ${is_comment} EQUAL 0)
|
|
||||||
string(REPLACE "=" ";" line_split ${line})
|
|
||||||
list(GET line_split 0 variable_name)
|
|
||||||
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
|
||||||
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
|
||||||
set(line_to_add ${line_to_add} ${line})
|
|
||||||
foreach (line_to_append ${line_to_add})
|
|
||||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
|
||||||
endforeach()
|
|
||||||
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
|
||||||
endif()
|
|
||||||
set(line_to_add "")
|
|
||||||
else()
|
|
||||||
set(line_to_add ${line_to_add} ${line})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
message(STATUS "Resource file integrity check complete")
|
|
||||||
|
|
||||||
# Copy navmesh data on first build and extract it
|
# Copy navmesh data on first build and extract it
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=1
|
PROJECT_VERSION_MINOR=0
|
||||||
PROJECT_VERSION_PATCH=1
|
PROJECT_VERSION_PATCH=4
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
|
# The network version.
|
||||||
|
# 171023 - Darkflame Universe client
|
||||||
|
# 171022 - Unmodded client
|
||||||
|
NET_VERSION=171022
|
||||||
# Debugging
|
# Debugging
|
||||||
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
__dynamic=1
|
__dynamic=1
|
||||||
@@ -18,5 +22,3 @@ __maria_db_connector_compile_jobs__=1
|
|||||||
__enable_testing__=1
|
__enable_testing__=1
|
||||||
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
# The path to OpenSSL. Change this if your OpenSSL install path is different than the default.
|
||||||
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
OPENSSL_ROOT_DIR=/usr/local/opt/openssl@3/
|
||||||
# Uncomment the below line to cache the entire CDClient into memory
|
|
||||||
# CDCLIENT_CACHE_ALL=1
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j<number>` where number i
|
|||||||
### Notes
|
### Notes
|
||||||
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
|
||||||
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
|
||||||
* If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
|
* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023.
|
||||||
|
|
||||||
## Configuring your server
|
## Configuring your server
|
||||||
This server has a few steps that need to be taken to configure the server for your use case.
|
This server has a few steps that need to be taken to configure the server for your use case.
|
||||||
@@ -338,7 +338,7 @@ This is a Work in Progress, but below are some quick links to documentaion for s
|
|||||||
## Former Contributors
|
## Former Contributors
|
||||||
* TheMachine
|
* TheMachine
|
||||||
* Matthew
|
* Matthew
|
||||||
* [Raine](https://github.com/uwainium)
|
* [Raine](https://github.com/Rainebannister)
|
||||||
* Bricknave
|
* Bricknave
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ namespace Game {
|
|||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
std::mt19937 randomEngine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger();
|
dLogger* SetupLogger();
|
||||||
@@ -55,12 +54,34 @@ int main(int argc, char** argv) {
|
|||||||
Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||||
Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__);
|
Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__);
|
||||||
|
|
||||||
Database::Connect(Game::config);
|
//Connect to the MySQL Database
|
||||||
|
std::string mysql_host = Game::config->GetValue("mysql_host");
|
||||||
|
std::string mysql_database = Game::config->GetValue("mysql_database");
|
||||||
|
std::string mysql_username = Game::config->GetValue("mysql_username");
|
||||||
|
std::string mysql_password = Game::config->GetValue("mysql_password");
|
||||||
|
|
||||||
// Get Master server IP and port
|
try {
|
||||||
SocketDescriptor masterSock = Database::Connection->GetMasterServerIP();
|
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
||||||
|
} catch (sql::SQLException& ex) {
|
||||||
|
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s", ex.what());
|
||||||
|
Database::Destroy("AuthServer");
|
||||||
|
delete Game::server;
|
||||||
|
delete Game::logger;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
//Find out the master's IP:
|
||||||
|
std::string masterIP;
|
||||||
|
uint32_t masterPort = 1500;
|
||||||
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
|
while (res->next()) {
|
||||||
|
masterIP = res->getString(1).c_str();
|
||||||
|
masterPort = res->getInt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
uint32_t maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
@@ -68,7 +89,7 @@ int main(int argc, char** argv) {
|
|||||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||||
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
||||||
|
|
||||||
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterSock.hostAddress, masterSock.port, ServerType::Auth, Game::config, &Game::shouldShutdown);
|
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::shouldShutdown);
|
||||||
|
|
||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
@@ -107,7 +128,18 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= sqlPingTime) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
Database::Connection->GetMasterServerIP();
|
//Find out the master's IP for absolutely no reason:
|
||||||
|
std::string masterIP;
|
||||||
|
uint32_t masterPort;
|
||||||
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
|
while (res->next()) {
|
||||||
|
masterIP = res->getString(1).c_str();
|
||||||
|
masterPort = res->getInt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
@@ -116,7 +148,9 @@ int main(int argc, char** argv) {
|
|||||||
t += std::chrono::milliseconds(authFrameDelta); //Auth can run at a lower "fps"
|
t += std::chrono::milliseconds(authFrameDelta); //Auth can run at a lower "fps"
|
||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Delete our objects here:
|
||||||
|
Database::Destroy("AuthServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
delete Game::config;
|
delete Game::config;
|
||||||
|
|||||||
@@ -31,13 +31,16 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
ReadWordlistDCF("blacklist.dcf", false);
|
ReadWordlistDCF("blacklist.dcf", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read player names that are ok as well:
|
//Read player names that are ok as well:
|
||||||
auto names = Database::Connection->GetAllCharacterNames();
|
auto stmt = Database::CreatePreppedStmt("select name from charinfo;");
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
for (auto& name : names) {
|
while (res->next()) {
|
||||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
std::string line = res->getString(1).c_str();
|
||||||
m_ApprovedWords.push_back(CalculateHash(name));
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
||||||
|
m_ApprovedWords.push_back(CalculateHash(line));
|
||||||
}
|
}
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
dChatFilter::~dChatFilter() {
|
dChatFilter::~dChatFilter() {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "PacketUtils.h"
|
#include "PacketUtils.h"
|
||||||
#include "BitStreamUtils.h"
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
@@ -76,11 +75,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(0);
|
bitStream.Write<uint8_t>(0);
|
||||||
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
|
||||||
bitStream.Write((uint16_t)friends.size());
|
bitStream.Write((uint16_t)friends.size());
|
||||||
@@ -413,21 +412,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
bitStream.Write<uint8_t>(8);
|
bitStream.Write<uint8_t>(8);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
bitStream.Write(LUWString(senderName));
|
PacketUtils::WritePacketWString(senderName, 33, &bitStream);
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
bitStream.Write(LUWString(otherName));
|
PacketUtils::WritePacketWString(otherName, 33, &bitStream);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //teams?
|
bitStream.Write<uint8_t>(0); //teams?
|
||||||
bitStream.Write(LUWString(message, 512));
|
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
||||||
|
|
||||||
SystemAddress sysAddr = otherMember->sysAddr;
|
SystemAddress sysAddr = otherMember->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -435,7 +434,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||||
LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
|
LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet);
|
||||||
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
|
||||||
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
||||||
|
|
||||||
@@ -452,21 +451,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the sender:
|
//To the sender:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
bitStream.Write(LUWString(goonAName));
|
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
bitStream.Write(LUWString(goonBName));
|
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(0); //success
|
bitStream.Write<uint8_t>(0); //success
|
||||||
bitStream.Write(LUWString(message, 512));
|
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
||||||
|
|
||||||
SystemAddress sysAddr = goonA->sysAddr;
|
SystemAddress sysAddr = goonA->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -475,21 +474,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the receiver:
|
//To the receiver:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonB->playerID);
|
bitStream.Write(goonB->playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint8_t>(7);
|
bitStream.Write<uint8_t>(7);
|
||||||
bitStream.Write<unsigned int>(69);
|
bitStream.Write<unsigned int>(69);
|
||||||
bitStream.Write(LUWString(goonAName));
|
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
bitStream.Write<uint16_t>(0);
|
bitStream.Write<uint16_t>(0);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||||
bitStream.Write(LUWString(goonBName));
|
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
||||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||||
bitStream.Write<uint8_t>(3); //new whisper
|
bitStream.Write<uint8_t>(3); //new whisper
|
||||||
bitStream.Write(LUWString(message, 512));
|
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
||||||
|
|
||||||
SystemAddress sysAddr = goonB->sysAddr;
|
SystemAddress sysAddr = goonB->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -710,13 +709,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||||
|
|
||||||
bitStream.Write(LUWString(sender->playerName.c_str()));
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -725,7 +724,7 @@ void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender)
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -752,7 +751,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -777,7 +776,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -794,7 +793,7 @@ void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64Play
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -823,7 +822,7 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -849,7 +848,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -883,16 +882,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(friendData->playerID);
|
bitStream.Write(friendData->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
||||||
bitStream.Write<uint8_t>(notifyType);
|
bitStream.Write<uint8_t>(notifyType);
|
||||||
|
|
||||||
std::string playerName = playerData->playerName.c_str();
|
std::string playerName = playerData->playerName.c_str();
|
||||||
|
|
||||||
bitStream.Write(LUWString(playerName));
|
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
||||||
|
|
||||||
bitStream.Write(playerData->zoneID.GetMapID());
|
bitStream.Write(playerData->zoneID.GetMapID());
|
||||||
bitStream.Write(playerData->zoneID.GetInstanceID());
|
bitStream.Write(playerData->zoneID.GetInstanceID());
|
||||||
@@ -922,12 +921,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||||
bitStream.Write(LUWString(sender->playerName.c_str()));
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -938,16 +937,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen
|
|||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
||||||
bitStream.Write(responseCode);
|
bitStream.Write(responseCode);
|
||||||
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
|
||||||
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
// Then write the player name
|
// Then write the player name
|
||||||
bitStream.Write(LUWString(sender->playerName.c_str()));
|
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
||||||
// Then if this is an acceptance code, write the following extra info.
|
// Then if this is an acceptance code, write the following extra info.
|
||||||
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
if (responseCode == eAddFriendResponseType::ACCEPTED) {
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
@@ -963,13 +962,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers
|
|||||||
if (!receiver) return;
|
if (!receiver) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(receiver->playerID);
|
bitStream.Write(receiver->playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
bitStream.Write(LUWString(personToRemove));
|
PacketUtils::WritePacketWString(personToRemove, 33, &bitStream);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ namespace Game {
|
|||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
std::mt19937 randomEngine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -77,10 +76,34 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Connect(Game::config);
|
//Connect to the MySQL Database
|
||||||
|
std::string mysql_host = Game::config->GetValue("mysql_host");
|
||||||
|
std::string mysql_database = Game::config->GetValue("mysql_database");
|
||||||
|
std::string mysql_username = Game::config->GetValue("mysql_username");
|
||||||
|
std::string mysql_password = Game::config->GetValue("mysql_password");
|
||||||
|
|
||||||
// Get Master server IP and port
|
try {
|
||||||
SocketDescriptor masterSock = Database::Connection->GetMasterServerIP();
|
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
||||||
|
} catch (sql::SQLException& ex) {
|
||||||
|
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what());
|
||||||
|
Database::Destroy("ChatServer");
|
||||||
|
delete Game::server;
|
||||||
|
delete Game::logger;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find out the master's IP:
|
||||||
|
std::string masterIP;
|
||||||
|
uint32_t masterPort = 1000;
|
||||||
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
|
while (res->next()) {
|
||||||
|
masterIP = res->getString(1).c_str();
|
||||||
|
masterPort = res->getInt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
uint32_t maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
@@ -88,11 +111,9 @@ int main(int argc, char** argv) {
|
|||||||
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
if (Game::config->GetValue("max_clients") != "") maxClients = std::stoi(Game::config->GetValue("max_clients"));
|
||||||
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
if (Game::config->GetValue("port") != "") ourPort = std::atoi(Game::config->GetValue("port").c_str());
|
||||||
|
|
||||||
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterSock.hostAddress, masterSock.port, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
Game::server = new dServer(Game::config->GetValue("external_ip"), ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::shouldShutdown);
|
||||||
|
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
|
||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
|
||||||
|
|
||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
@@ -131,7 +152,18 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Every 10 min we ping our sql server to keep it alive hopefully:
|
//Every 10 min we ping our sql server to keep it alive hopefully:
|
||||||
if (framesSinceLastSQLPing >= sqlPingTime) {
|
if (framesSinceLastSQLPing >= sqlPingTime) {
|
||||||
Database::Connection->GetMasterServerIP();
|
//Find out the master's IP for absolutely no reason:
|
||||||
|
std::string masterIP;
|
||||||
|
uint32_t masterPort;
|
||||||
|
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
||||||
|
auto res = stmt->executeQuery();
|
||||||
|
while (res->next()) {
|
||||||
|
masterIP = res->getString(1).c_str();
|
||||||
|
masterPort = res->getInt(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
@@ -141,8 +173,8 @@ int main(int argc, char** argv) {
|
|||||||
std::this_thread::sleep_until(t);
|
std::this_thread::sleep_until(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete our objects here:
|
//Delete our objects here:
|
||||||
Database::Destroy();
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
delete Game::config;
|
delete Game::config;
|
||||||
|
|||||||
@@ -6,11 +6,10 @@
|
|||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "PacketUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
#include "ChatPackets.h"
|
|
||||||
|
|
||||||
PlayerContainer::PlayerContainer() {
|
PlayerContainer::PlayerContainer() {
|
||||||
}
|
}
|
||||||
@@ -41,7 +40,14 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
mPlayers.insert(std::make_pair(data->playerID, data));
|
mPlayers.insert(std::make_pair(data->playerID, data));
|
||||||
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
Game::logger->Log("PlayerContainer", "Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
||||||
|
|
||||||
Database::Connection->InsertIntoActivityLog(data->playerID, 0, time(nullptr), data->zoneID.GetMapID());
|
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
||||||
|
|
||||||
|
insertLog->setInt(1, data->playerID);
|
||||||
|
insertLog->setInt(2, 0);
|
||||||
|
insertLog->setUInt64(3, time(nullptr));
|
||||||
|
insertLog->setInt(4, data->zoneID.GetMapID());
|
||||||
|
|
||||||
|
insertLog->executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::RemovePlayer(Packet* packet) {
|
void PlayerContainer::RemovePlayer(Packet* packet) {
|
||||||
@@ -78,7 +84,14 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID);
|
Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID);
|
||||||
mPlayers.erase(playerID);
|
mPlayers.erase(playerID);
|
||||||
|
|
||||||
Database::Connection->InsertIntoActivityLog(playerID, 1, time(nullptr), player->zoneID.GetMapID());
|
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
||||||
|
|
||||||
|
insertLog->setInt(1, playerID);
|
||||||
|
insertLog->setInt(2, 1);
|
||||||
|
insertLog->setUInt64(3, time(nullptr));
|
||||||
|
insertLog->setInt(4, player->zoneID.GetMapID());
|
||||||
|
|
||||||
|
insertLog->executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::MuteUpdate(Packet* packet) {
|
void PlayerContainer::MuteUpdate(Packet* packet) {
|
||||||
@@ -133,7 +146,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -194,14 +207,6 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||||
if (team->memberIDs.size() >= 4){
|
|
||||||
Game::logger->Log("PlayerContainer", "Tried to add player to team that already had 4 players");
|
|
||||||
auto* player = GetPlayerData(playerID);
|
|
||||||
if (!player) return;
|
|
||||||
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
|
||||||
|
|
||||||
if (index != team->memberIDs.end()) return;
|
if (index != team->memberIDs.end()) return;
|
||||||
@@ -340,7 +345,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
|
|||||||
@@ -1,93 +1,35 @@
|
|||||||
#include "MySQLMigration.h"
|
#include "BrickByBrickFix.h"
|
||||||
|
|
||||||
#include <istream>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "CDClientDatabase.h"
|
|
||||||
#include "Game.h"
|
|
||||||
#include "GeneralUtils.h"
|
|
||||||
#include "dLogger.h"
|
|
||||||
#include "BinaryPathFinder.h"
|
|
||||||
#include "ZCompression.h"
|
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
|
|
||||||
#include "../MySQL.h"
|
#include "Database.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "ZCompression.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
void MigrationRunner::RunMigrations(DatabaseBase* db) {
|
//! Forward declarations
|
||||||
auto database = dynamic_cast<MySQLDatabase*>(db);
|
|
||||||
|
|
||||||
auto* stmt = database->CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase();
|
||||||
stmt->execute();
|
void WriteSd0Magic(char* input, uint32_t chunkSize);
|
||||||
delete stmt;
|
bool CheckSd0Magic(sql::Blob* streamToCheck);
|
||||||
|
|
||||||
sql::SQLString finalSQL = "";
|
/**
|
||||||
bool runSd0Migrations = false;
|
* @brief Truncates all models with broken data from the database.
|
||||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/mysql").string())) {
|
*
|
||||||
auto migration = Migration::LoadMigration("dlu", "mysql", entry);
|
* @return The number of models deleted
|
||||||
|
*/
|
||||||
if (migration.data.empty()) {
|
uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = database->CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
|
||||||
stmt->setString(1, migration.name.c_str());
|
|
||||||
auto* res = stmt->executeQuery();
|
|
||||||
bool doExit = res->next();
|
|
||||||
delete res;
|
|
||||||
delete stmt;
|
|
||||||
if (doExit) continue;
|
|
||||||
|
|
||||||
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
|
||||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
|
||||||
runSd0Migrations = true;
|
|
||||||
} else {
|
|
||||||
finalSQL.append(migration.data.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt = database->CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
|
||||||
stmt->setString(1, migration.name.c_str());
|
|
||||||
stmt->execute();
|
|
||||||
delete stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finalSQL.empty() && !runSd0Migrations) {
|
|
||||||
Game::logger->Log("MigrationRunner", "Server database is up to date.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!finalSQL.empty()) {
|
|
||||||
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
|
|
||||||
std::unique_ptr<sql::Statement> simpleStatement(Database::CreateStmt());
|
|
||||||
for (auto& query : migration) {
|
|
||||||
try {
|
|
||||||
if (query.empty()) continue;
|
|
||||||
simpleStatement->execute(query.c_str());
|
|
||||||
} catch (sql::SQLException& e) {
|
|
||||||
Game::logger->Log("MigrationRunner", "Encountered error running migration: %s", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do this last on the off chance none of the other migrations have been run yet.
|
|
||||||
if (runSd0Migrations) {
|
|
||||||
uint32_t numberOfUpdatedModels = UpdateBrickByBrickModelsToSd0();
|
|
||||||
Game::logger->Log("MasterServer", "%i models were updated from zlib to sd0.", numberOfUpdatedModels);
|
|
||||||
|
|
||||||
uint32_t numberOfTruncatedModels = TruncateBrokenBrickByBrickXml();
|
|
||||||
Game::logger->Log("MasterServer", "%i models were truncated from the database.", numberOfTruncatedModels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t TruncateBrokenBrickByBrickXml(MySQLDatabase* database) {
|
|
||||||
uint32_t modelsTruncated{};
|
uint32_t modelsTruncated{};
|
||||||
auto modelsToTruncate = GetModelsFromDatabase(database);
|
auto modelsToTruncate = GetModelsFromDatabase();
|
||||||
|
bool previousCommitValue = Database::GetAutoCommit();
|
||||||
bool previousCommitValue = database->GetAutoCommit();
|
Database::SetAutoCommit(false);
|
||||||
database->SetAutoCommit(false);
|
|
||||||
|
|
||||||
while (modelsToTruncate->next()) {
|
while (modelsToTruncate->next()) {
|
||||||
std::unique_ptr<sql::PreparedStatement> ugcModelToDelete(database->CreatePreppedStmt("DELETE FROM ugc WHERE ugc.id = ?;"));
|
std::unique_ptr<sql::PreparedStatement> ugcModelToDelete(Database::CreatePreppedStmt("DELETE FROM ugc WHERE ugc.id = ?;"));
|
||||||
std::unique_ptr<sql::PreparedStatement> pcModelToDelete(database->CreatePreppedStmt("DELETE FROM properties_contents WHERE ugc_id = ?;"));
|
std::unique_ptr<sql::PreparedStatement> pcModelToDelete(Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE ugc_id = ?;"));
|
||||||
std::string completeUncompressedModel{};
|
std::string completeUncompressedModel{};
|
||||||
uint32_t chunkCount{};
|
uint32_t chunkCount{};
|
||||||
uint64_t modelId = modelsToTruncate->getInt(1);
|
uint64_t modelId = modelsToTruncate->getInt(1);
|
||||||
@@ -153,8 +95,8 @@ uint32_t TruncateBrokenBrickByBrickXml(MySQLDatabase* database) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
database->Commit();
|
Database::Commit();
|
||||||
database->SetAutoCommit(previousCommitValue);
|
Database::SetAutoCommit(previousCommitValue);
|
||||||
return modelsTruncated;
|
return modelsTruncated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,14 +106,12 @@ uint32_t TruncateBrokenBrickByBrickXml(MySQLDatabase* database) {
|
|||||||
*
|
*
|
||||||
* @return The number of models updated to SD0
|
* @return The number of models updated to SD0
|
||||||
*/
|
*/
|
||||||
uint32_t UpdateBrickByBrickModelsToSd0(MySQLDatabase* database) {
|
uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
||||||
uint32_t updatedModels = 0;
|
uint32_t updatedModels = 0;
|
||||||
auto modelsToUpdate = GetModelsFromDatabase();
|
auto modelsToUpdate = GetModelsFromDatabase();
|
||||||
|
auto previousAutoCommitState = Database::GetAutoCommit();
|
||||||
auto previousAutoCommitState = database->GetAutoCommit();
|
Database::SetAutoCommit(false);
|
||||||
database->SetAutoCommit(false);
|
std::unique_ptr<sql::PreparedStatement> insertionStatement(Database::CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> insertionStatement(database->CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
|
|
||||||
while (modelsToUpdate->next()) {
|
while (modelsToUpdate->next()) {
|
||||||
int64_t modelId = modelsToUpdate->getInt64(1);
|
int64_t modelId = modelsToUpdate->getInt64(1);
|
||||||
std::unique_ptr<sql::Blob> oldLxfml(modelsToUpdate->getBlob(2));
|
std::unique_ptr<sql::Blob> oldLxfml(modelsToUpdate->getBlob(2));
|
||||||
@@ -210,14 +150,13 @@ uint32_t UpdateBrickByBrickModelsToSd0(MySQLDatabase* database) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Database::Commit();
|
||||||
database->Commit();
|
Database::SetAutoCommit(previousAutoCommitState);
|
||||||
database->SetAutoCommit(previousAutoCommitState);
|
|
||||||
return updatedModels;
|
return updatedModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase(MySQLDatabase* database) {
|
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase() {
|
||||||
std::unique_ptr<sql::PreparedStatement> modelsRawDataQuery(database->CreatePreppedStmt("SELECT id, lxfml FROM ugc;"));
|
std::unique_ptr<sql::PreparedStatement> modelsRawDataQuery(Database::CreatePreppedStmt("SELECT id, lxfml FROM ugc;"));
|
||||||
return std::unique_ptr<sql::ResultSet>(modelsRawDataQuery->executeQuery());
|
return std::unique_ptr<sql::ResultSet>(modelsRawDataQuery->executeQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
20
dCommon/BrickByBrickFix.h
Normal file
20
dCommon/BrickByBrickFix.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace BrickByBrickFix {
|
||||||
|
/**
|
||||||
|
* @brief Deletes all broken BrickByBrick models that have invalid XML
|
||||||
|
*
|
||||||
|
* @return The number of BrickByBrick models that were truncated
|
||||||
|
*/
|
||||||
|
uint32_t TruncateBrokenBrickByBrickXml();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates all BrickByBrick models in the database to be
|
||||||
|
* in the sd0 format as opposed to a zlib compressed format.
|
||||||
|
*
|
||||||
|
* @return The number of BrickByBrick models that were updated
|
||||||
|
*/
|
||||||
|
uint32_t UpdateBrickByBrickModelsToSd0();
|
||||||
|
};
|
||||||
@@ -12,8 +12,9 @@ set(DCOMMON_SOURCES
|
|||||||
"NiPoint3.cpp"
|
"NiPoint3.cpp"
|
||||||
"NiQuaternion.cpp"
|
"NiQuaternion.cpp"
|
||||||
"SHA512.cpp"
|
"SHA512.cpp"
|
||||||
"Demangler.cpp"
|
"Type.cpp"
|
||||||
"ZCompression.cpp"
|
"ZCompression.cpp"
|
||||||
|
"BrickByBrickFix.cpp"
|
||||||
"BinaryPathFinder.cpp"
|
"BinaryPathFinder.cpp"
|
||||||
"FdbToSqlite.cpp"
|
"FdbToSqlite.cpp"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
#include "Demangler.h"
|
|
||||||
#ifdef __GNUG__
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
std::string Demangler::Demangle(const char* name) {
|
|
||||||
// some arbitrary value to eliminate the compiler warning
|
|
||||||
// -4 is not a valid return value for __cxa_demangle so we'll use that.
|
|
||||||
int status = -4;
|
|
||||||
|
|
||||||
// __cxa_demangle requires that we free the returned char*
|
|
||||||
std::unique_ptr<char, void (*)(void*)> res{
|
|
||||||
abi::__cxa_demangle(name, NULL, NULL, &status),
|
|
||||||
std::free
|
|
||||||
};
|
|
||||||
|
|
||||||
return (status == 0) ? res.get() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
#else // __GNUG__
|
|
||||||
|
|
||||||
// does nothing if not g++
|
|
||||||
std::string Demangler::Demangle(const char* name) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __GNUG__
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Demangler {
|
|
||||||
// Given a char* containing a mangled name, return a std::string containing the demangled name.
|
|
||||||
// If the function fails for any reason, it returns an empty string.
|
|
||||||
std::string Demangle(const char* name);
|
|
||||||
}
|
|
||||||
@@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Demangler.h"
|
#include "Type.h"
|
||||||
|
|
||||||
void GenerateDump() {
|
void GenerateDump() {
|
||||||
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
||||||
@@ -122,43 +122,41 @@ void CatchUnhandled(int sig) {
|
|||||||
if (Diagnostics::GetProduceMemoryDump()) {
|
if (Diagnostics::GetProduceMemoryDump()) {
|
||||||
GenerateDump();
|
GenerateDump();
|
||||||
}
|
}
|
||||||
constexpr uint8_t MaxStackTrace = 32;
|
|
||||||
void* array[MaxStackTrace];
|
void* array[10];
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
// get void*'s for all entries on the stack
|
// get void*'s for all entries on the stack
|
||||||
size = backtrace(array, MaxStackTrace);
|
size = backtrace(array, 10);
|
||||||
|
|
||||||
# if defined(__GNUG__)
|
#if defined(__GNUG__) and defined(__dynamic)
|
||||||
|
|
||||||
// Loop through the returned addresses, and get the symbols to be demangled
|
// Loop through the returned addresses, and get the symbols to be demangled
|
||||||
char** strings = backtrace_symbols(array, size);
|
char** strings = backtrace_symbols(array, size);
|
||||||
|
|
||||||
// Print the stack trace
|
// Print the stack trace
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]'
|
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]' and extract the function name
|
||||||
// and extract '_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress' from it to be demangled into a proper name
|
|
||||||
std::string functionName = strings[i];
|
std::string functionName = strings[i];
|
||||||
std::string::size_type start = functionName.find('(');
|
std::string::size_type start = functionName.find('(');
|
||||||
std::string::size_type end = functionName.find('+');
|
std::string::size_type end = functionName.find('+');
|
||||||
if (start != std::string::npos && end != std::string::npos) {
|
if (start != std::string::npos && end != std::string::npos) {
|
||||||
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
std::string demangled = functionName.substr(start + 1, end - start - 1);
|
||||||
|
|
||||||
demangled = Demangler::Demangle(demangled.c_str());
|
demangled = demangle(functionName.c_str());
|
||||||
|
|
||||||
// If the demangled string is not empty, then we can replace the mangled string with the demangled one
|
if (demangled.empty()) {
|
||||||
if (!demangled.empty()) {
|
Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str());
|
||||||
demangled.push_back('(');
|
} else {
|
||||||
demangled += functionName.substr(end);
|
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
||||||
functionName = demangled;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
|
||||||
}
|
}
|
||||||
# else // defined(__GNUG__)
|
#else
|
||||||
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
||||||
# endif // defined(__GNUG__)
|
#endif
|
||||||
|
|
||||||
FILE* file = fopen(fileName.c_str(), "w+");
|
FILE* file = fopen(fileName.c_str(), "w+");
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
@@ -168,7 +166,7 @@ void CatchUnhandled(int sig) {
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // __include_backtrace__
|
#else
|
||||||
|
|
||||||
struct backtrace_state* state = backtrace_create_state(
|
struct backtrace_state* state = backtrace_create_state(
|
||||||
Diagnostics::GetProcessFileName().c_str(),
|
Diagnostics::GetProcessFileName().c_str(),
|
||||||
@@ -179,7 +177,7 @@ void CatchUnhandled(int sig) {
|
|||||||
struct bt_ctx ctx = { state, 0 };
|
struct bt_ctx ctx = { state, 0 };
|
||||||
Bt(state);
|
Bt(state);
|
||||||
|
|
||||||
#endif // __include_backtrace__
|
#endif
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ class dConfig;
|
|||||||
class RakPeerInterface;
|
class RakPeerInterface;
|
||||||
class AssetManager;
|
class AssetManager;
|
||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
class EntityManager;
|
|
||||||
class dZoneManager;
|
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
extern dLogger* logger;
|
extern dLogger* logger;
|
||||||
@@ -24,6 +22,4 @@ namespace Game {
|
|||||||
extern AssetManager* assetManager;
|
extern AssetManager* assetManager;
|
||||||
extern SystemAddress chatSysAddr;
|
extern SystemAddress chatSysAddr;
|
||||||
extern bool shouldShutdown;
|
extern bool shouldShutdown;
|
||||||
extern EntityManager* entityManager;
|
|
||||||
extern dZoneManager* zoneManager;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,29 @@ namespace GeneralUtils {
|
|||||||
*/
|
*/
|
||||||
bool CheckBit(int64_t value, uint32_t index);
|
bool CheckBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
|
// MARK: Random Number Generation
|
||||||
|
|
||||||
|
//! Generates a random number
|
||||||
|
/*!
|
||||||
|
\param min The minimum the generate from
|
||||||
|
\param max The maximum to generate to
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
||||||
|
// Make sure it is a numeric type
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
|
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
||||||
|
std::uniform_int_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
} else if (std::is_floating_point_v<T>) {
|
||||||
|
std::uniform_real_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream* inStream);
|
std::u16string ReadWString(RakNet::BitStream* inStream);
|
||||||
@@ -126,11 +149,6 @@ namespace GeneralUtils {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
T Parse(const char* value);
|
T Parse(const char* value);
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool Parse(const char* value) {
|
|
||||||
return std::stoi(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int32_t Parse(const char* value) {
|
inline int32_t Parse(const char* value) {
|
||||||
return std::stoi(value);
|
return std::stoi(value);
|
||||||
@@ -205,42 +223,4 @@ namespace GeneralUtils {
|
|||||||
std::hash<T> h;
|
std::hash<T> h;
|
||||||
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Random Number Generation
|
|
||||||
|
|
||||||
//! Generates a random number
|
|
||||||
/*!
|
|
||||||
\param min The minimum the generate from
|
|
||||||
\param max The maximum to generate to
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
|
||||||
// Make sure it is a numeric type
|
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
||||||
|
|
||||||
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
|
||||||
std::uniform_int_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
} else if (std::is_floating_point_v<T>) {
|
|
||||||
std::uniform_real_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
|
||||||
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
|
||||||
#ifdef _WIN32
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T GenerateRandomNumber() {
|
|
||||||
// Make sure it is a numeric type
|
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
||||||
|
|
||||||
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,33 +61,35 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
case LDF_TYPE_S32: {
|
||||||
int32_t data;
|
try {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<int32_t>(key, data);
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
returnValue = new LDFData<int32_t>(key, data);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_FLOAT: {
|
case LDF_TYPE_FLOAT: {
|
||||||
float data;
|
try {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
float data = strtof(ldfTypeAndValue.second.data(), &storage);
|
||||||
|
returnValue = new LDFData<float>(key, data);
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
returnValue = new LDFData<float>(key, data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_DOUBLE: {
|
case LDF_TYPE_DOUBLE: {
|
||||||
double data;
|
try {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
double data = strtod(ldfTypeAndValue.second.data(), &storage);
|
||||||
|
returnValue = new LDFData<double>(key, data);
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
returnValue = new LDFData<double>(key, data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +102,9 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = 0;
|
data = 0;
|
||||||
} else {
|
} else {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
try {
|
||||||
|
data = static_cast<uint32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -118,7 +122,9 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
try {
|
||||||
|
data = static_cast<bool>(strtol(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -129,22 +135,24 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
case LDF_TYPE_U64: {
|
||||||
uint64_t data;
|
try {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<uint64_t>(key, data);
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
returnValue = new LDFData<uint64_t>(key, data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_OBJID: {
|
case LDF_TYPE_OBJID: {
|
||||||
LWOOBJID data;
|
try {
|
||||||
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10));
|
||||||
|
returnValue = new LDFData<LWOOBJID>(key, data);
|
||||||
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
returnValue = new LDFData<LWOOBJID>(key, data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,19 +129,10 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const {
|
||||||
this->x += point.x;
|
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z);
|
||||||
this->y += point.y;
|
|
||||||
this->z += point.z;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3& NiPoint3::operator*=(const float scalar) {
|
|
||||||
this->x *= scalar;
|
|
||||||
this->y *= scalar;
|
|
||||||
this->z *= scalar;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {
|
||||||
|
|||||||
@@ -136,9 +136,7 @@ public:
|
|||||||
NiPoint3 operator+(const NiPoint3& point) const;
|
NiPoint3 operator+(const NiPoint3& point) const;
|
||||||
|
|
||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3& operator+=(const NiPoint3& point);
|
NiPoint3 operator+=(const NiPoint3& point) const;
|
||||||
|
|
||||||
NiPoint3& operator*=(const float scalar);
|
|
||||||
|
|
||||||
//! Operator for subtraction of vectors
|
//! Operator for subtraction of vectors
|
||||||
NiPoint3 operator-(const NiPoint3& point) const;
|
NiPoint3 operator-(const NiPoint3& point) const;
|
||||||
|
|||||||
27
dCommon/Type.cpp
Normal file
27
dCommon/Type.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include "Type.h"
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <memory>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
std::string demangle(const char* name) {
|
||||||
|
|
||||||
|
int status = -4; // some arbitrary value to eliminate the compiler warning
|
||||||
|
|
||||||
|
// enable c++11 by passing the flag -std=c++11 to g++
|
||||||
|
std::unique_ptr<char, void(*)(void*)> res{
|
||||||
|
abi::__cxa_demangle(name, NULL, NULL, &status),
|
||||||
|
std::free
|
||||||
|
};
|
||||||
|
|
||||||
|
return (status == 0) ? res.get() : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// does nothing if not g++
|
||||||
|
std::string demangle(const char* name) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
12
dCommon/Type.h
Normal file
12
dCommon/Type.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
std::string demangle(const char* name);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::string type(const T& t) {
|
||||||
|
|
||||||
|
return demangle(typeid(t).name());
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
free(m_Base);
|
delete m_Base;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
|
||||||
|
|
||||||
#pragma warning (disable:4251) //Disables SQL warnings
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
|||||||
#define CBITSTREAM RakNet::BitStream bitStream;
|
#define CBITSTREAM RakNet::BitStream bitStream;
|
||||||
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
||||||
#define CMSGHEADER BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
||||||
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
TRADE,
|
TRADE,
|
||||||
USER_CONTROL,
|
USER_CONTROL,
|
||||||
IGNORE_LIST,
|
IGNORE_LIST,
|
||||||
MULTI_ZONE_ENTRANCE,
|
ROCKET_LAUNCH_LUP,
|
||||||
BUFF_REAL, // the real buff component, should just be name BUFF
|
BUFF_REAL, // the real buff component, should just be name BUFF
|
||||||
INTERACTION_MANAGER,
|
INTERACTION_MANAGER,
|
||||||
DONATION_VENDOR,
|
DONATION_VENDOR,
|
||||||
|
|||||||
@@ -13,7 +13,15 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
//! The CDClient Database namespace
|
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
||||||
|
//#define CDCLIENT_CACHE_ALL
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file CDClientDatabase.hpp
|
||||||
|
\brief An interface between the CDClient.sqlite file and the server
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! The CDClient Database namespace
|
||||||
namespace CDClientDatabase {
|
namespace CDClientDatabase {
|
||||||
|
|
||||||
//! Opens a connection with the CDClient
|
//! Opens a connection with the CDClient
|
||||||
|
|||||||
@@ -38,53 +38,43 @@
|
|||||||
#include "CDFeatureGatingTable.h"
|
#include "CDFeatureGatingTable.h"
|
||||||
#include "CDRailActivatorComponent.h"
|
#include "CDRailActivatorComponent.h"
|
||||||
|
|
||||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
|
||||||
// A vanilla CDClient takes about 46MB of memory + the regular world data.
|
|
||||||
// #define CDCLIENT_CACHE_ALL
|
|
||||||
|
|
||||||
#ifdef CDCLIENT_CACHE_ALL
|
|
||||||
#define CDCLIENT_DONT_CACHE_TABLE(x) x
|
|
||||||
#else
|
|
||||||
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CDClientManager::CDClientManager() {
|
CDClientManager::CDClientManager() {
|
||||||
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
CDActivityRewardsTable::Instance();
|
||||||
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
CDAnimationsTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase());
|
CDBehaviorParameterTable::Instance();
|
||||||
CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
|
CDBehaviorTemplateTable::Instance();
|
||||||
CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
|
CDComponentsRegistryTable::Instance();
|
||||||
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
CDCurrencyTableTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
|
CDDestructibleComponentTable::Instance();
|
||||||
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
CDEmoteTableTable::Instance();
|
||||||
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
CDInventoryComponentTable::Instance();
|
||||||
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
CDItemComponentTable::Instance();
|
||||||
CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
|
CDItemSetsTable::Instance();
|
||||||
CDInventoryComponentTable::Instance().LoadValuesFromDatabase();
|
CDItemSetSkillsTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDItemComponentTable::Instance().LoadValuesFromDatabase());
|
CDLevelProgressionLookupTable::Instance();
|
||||||
CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
|
CDLootMatrixTable::Instance();
|
||||||
CDItemSetsTable::Instance().LoadValuesFromDatabase();
|
CDLootTableTable::Instance();
|
||||||
CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
|
CDMissionNPCComponentTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDLootMatrixTable::Instance().LoadValuesFromDatabase());
|
CDMissionTasksTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDLootTableTable::Instance().LoadValuesFromDatabase());
|
CDMissionsTable::Instance();
|
||||||
CDMissionEmailTable::Instance().LoadValuesFromDatabase();
|
CDObjectSkillsTable::Instance();
|
||||||
CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
|
CDObjectsTable::Instance();
|
||||||
CDMissionTasksTable::Instance().LoadValuesFromDatabase();
|
CDPhysicsComponentTable::Instance();
|
||||||
CDMissionsTable::Instance().LoadValuesFromDatabase();
|
CDRebuildComponentTable::Instance();
|
||||||
CDMovementAIComponentTable::Instance().LoadValuesFromDatabase();
|
CDScriptComponentTable::Instance();
|
||||||
CDObjectSkillsTable::Instance().LoadValuesFromDatabase();
|
CDSkillBehaviorTable::Instance();
|
||||||
CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase());
|
CDZoneTableTable::Instance();
|
||||||
CDPhysicsComponentTable::Instance().LoadValuesFromDatabase();
|
CDVendorComponentTable::Instance();
|
||||||
CDPackageComponentTable::Instance().LoadValuesFromDatabase();
|
CDActivitiesTable::Instance();
|
||||||
CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase();
|
CDPackageComponentTable::Instance();
|
||||||
CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase();
|
CDProximityMonitorComponentTable::Instance();
|
||||||
CDPropertyTemplateTable::Instance().LoadValuesFromDatabase();
|
CDMovementAIComponentTable::Instance();
|
||||||
CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
|
CDBrickIDTableTable::Instance();
|
||||||
CDRarityTableTable::Instance().LoadValuesFromDatabase();
|
CDRarityTableTable::Instance();
|
||||||
CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
|
CDMissionEmailTable::Instance();
|
||||||
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
CDRewardsTable::Instance();
|
||||||
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
CDPropertyEntranceComponentTable::Instance();
|
||||||
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
CDPropertyTemplateTable::Instance();
|
||||||
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
CDFeatureGatingTable::Instance();
|
||||||
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
CDRailActivatorComponentTable::Instance();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
set(DDATABASE_SOURCES "CDClientDatabase.cpp"
|
set(DDATABASE_SOURCES "CDClientDatabase.cpp"
|
||||||
"CDClientManager.cpp"
|
"CDClientManager.cpp"
|
||||||
"Database.cpp")
|
"Database.cpp"
|
||||||
|
"MigrationRunner.cpp")
|
||||||
|
|
||||||
add_subdirectory(Tables)
|
add_subdirectory(Tables)
|
||||||
|
|
||||||
@@ -8,17 +9,5 @@ foreach(file ${DDATABASE_TABLES_SOURCES})
|
|||||||
set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Tables/${file}")
|
set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Tables/${file}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_subdirectory(Databases)
|
|
||||||
|
|
||||||
foreach (file ${DDATABASE_DATABASES_SOURCES})
|
|
||||||
set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Databases/${file}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_subdirectory(Databases/Migrations)
|
|
||||||
|
|
||||||
foreach (file ${DDATABASE_DATABASES_MIGRATIONS_SOURCES})
|
|
||||||
set(DDATABASE_SOURCES ${DDATABASE_SOURCES} "Databases/Migrations/${file}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_library(dDatabase STATIC ${DDATABASE_SOURCES})
|
add_library(dDatabase STATIC ${DDATABASE_SOURCES})
|
||||||
target_link_libraries(dDatabase sqlite3 mariadbConnCpp)
|
target_link_libraries(dDatabase sqlite3 mariadbConnCpp)
|
||||||
|
|||||||
@@ -1,26 +1,118 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#include "Databases/MySQL.h"
|
#pragma warning (disable:4251) //Disables SQL warnings
|
||||||
|
|
||||||
void Database::Connect(dConfig* config) {
|
sql::Driver* Database::driver;
|
||||||
bool useSqlite = true;
|
sql::Connection* Database::con;
|
||||||
if (config->GetValue("mysql_host") != "" && config->GetValue("mysql_database") != "" && config->GetValue("mysql_username") != "" && config->GetValue("mysql_password") != "") {
|
sql::Properties Database::props;
|
||||||
useSqlite = false;
|
std::string Database::database;
|
||||||
}
|
|
||||||
|
|
||||||
if (useSqlite) {
|
void Database::Connect(const string& host, const string& database, const string& username, const string& password) {
|
||||||
|
|
||||||
|
//To bypass debug issues:
|
||||||
|
const char* szDatabase = database.c_str();
|
||||||
|
const char* szUsername = username.c_str();
|
||||||
|
const char* szPassword = password.c_str();
|
||||||
|
|
||||||
|
driver = sql::mariadb::get_driver_instance();
|
||||||
|
|
||||||
|
sql::Properties properties;
|
||||||
|
// The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where
|
||||||
|
// 1) it tries to parse a database from the connection string (like in tcp://localhost:3001/darkflame) based on the
|
||||||
|
// presence of a /
|
||||||
|
// 2) even avoiding that, the connector still assumes you're connecting with a tcp socket
|
||||||
|
// So, what we do in the presence of a unix socket or pipe is to set the hostname to the protocol and localhost,
|
||||||
|
// which avoids parsing errors while still ensuring the correct connection type is used, and then setting the appropriate
|
||||||
|
// property manually (which the URL parsing fails to do)
|
||||||
|
const std::string UNIX_PROTO = "unix://";
|
||||||
|
const std::string PIPE_PROTO = "pipe://";
|
||||||
|
if (host.find(UNIX_PROTO) == 0) {
|
||||||
|
properties["hostName"] = "unix://localhost";
|
||||||
|
properties["localSocket"] = host.substr(UNIX_PROTO.length()).c_str();
|
||||||
|
} else if (host.find(PIPE_PROTO) == 0) {
|
||||||
|
properties["hostName"] = "pipe://localhost";
|
||||||
|
properties["pipe"] = host.substr(PIPE_PROTO.length()).c_str();
|
||||||
|
} else {
|
||||||
|
properties["hostName"] = host.c_str();
|
||||||
|
}
|
||||||
|
properties["user"] = szUsername;
|
||||||
|
properties["password"] = szPassword;
|
||||||
|
properties["autoReconnect"] = "true";
|
||||||
|
|
||||||
|
Database::props = properties;
|
||||||
|
Database::database = database;
|
||||||
|
|
||||||
|
Database::Connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::Connect() {
|
||||||
|
// `connect(const Properties& props)` segfaults in windows debug, but
|
||||||
|
// `connect(const SQLString& host, const SQLString& user, const SQLString& pwd)` doesn't handle pipes/unix sockets correctly
|
||||||
|
if (Database::props.find("localSocket") != Database::props.end() || Database::props.find("pipe") != Database::props.end()) {
|
||||||
|
con = driver->connect(Database::props);
|
||||||
} else {
|
} else {
|
||||||
Database::Connection = new MySQLDatabase(config->GetValue("mysql_host"), config->GetValue("mysql_database"), config->GetValue("mysql_username"), config->GetValue("mysql_password"));
|
con = driver->connect(Database::props["hostName"].c_str(), Database::props["user"].c_str(), Database::props["password"].c_str());
|
||||||
Database::ConnectionType = eConnectionTypes::MYSQL;
|
}
|
||||||
|
con->setSchema(Database::database.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::Destroy(std::string source, bool log) {
|
||||||
|
if (!con) return;
|
||||||
|
|
||||||
|
if (log) {
|
||||||
|
if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!", source.c_str());
|
||||||
|
else Game::logger->Log("Database", "Destroying MySQL connection!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Connection->Connect();
|
con->close();
|
||||||
|
delete con;
|
||||||
|
} //Destroy
|
||||||
|
|
||||||
|
sql::Statement* Database::CreateStmt() {
|
||||||
|
sql::Statement* toReturn = con->createStatement();
|
||||||
|
return toReturn;
|
||||||
|
} //CreateStmt
|
||||||
|
|
||||||
|
sql::PreparedStatement* Database::CreatePreppedStmt(const std::string& query) {
|
||||||
|
const char* test = query.c_str();
|
||||||
|
size_t size = query.length();
|
||||||
|
sql::SQLString str(test, size);
|
||||||
|
|
||||||
|
if (!con) {
|
||||||
|
Connect();
|
||||||
|
Game::logger->Log("Database", "Trying to reconnect to MySQL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!con->isValid() || con->isClosed()) {
|
||||||
|
delete con;
|
||||||
|
|
||||||
|
con = nullptr;
|
||||||
|
|
||||||
|
Connect();
|
||||||
|
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* stmt = con->prepareStatement(str);
|
||||||
|
|
||||||
|
return stmt;
|
||||||
|
} //CreatePreppedStmt
|
||||||
|
|
||||||
|
void Database::Commit() {
|
||||||
|
Database::con->commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::Destroy() {
|
bool Database::GetAutoCommit() {
|
||||||
Database::Connection->Destroy();
|
// TODO This should not just access a pointer. A future PR should update this
|
||||||
delete Database::Connection;
|
// to check for null and throw an error if the connection is not valid.
|
||||||
|
return con->getAutoCommit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Database::SetAutoCommit(bool value) {
|
||||||
|
// TODO This should not just access a pointer. A future PR should update this
|
||||||
|
// to check for null and throw an error if the connection is not valid.
|
||||||
|
Database::con->setAutoCommit(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <conncpp.hpp>
|
||||||
|
|
||||||
#include "Databases/DatabaseBase.h"
|
class MySqlException : public std::runtime_error {
|
||||||
|
public:
|
||||||
class dConfig;
|
MySqlException() : std::runtime_error("MySQL error!") {}
|
||||||
|
MySqlException(const std::string& msg) : std::runtime_error(msg.c_str()) {}
|
||||||
|
};
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
|
private:
|
||||||
|
static sql::Driver* driver;
|
||||||
|
static sql::Connection* con;
|
||||||
|
static sql::Properties props;
|
||||||
|
static std::string database;
|
||||||
public:
|
public:
|
||||||
static DatabaseBase* Connection;
|
static void Connect(const std::string& host, const std::string& database, const std::string& username, const std::string& password);
|
||||||
static eConnectionTypes ConnectionType;
|
static void Connect();
|
||||||
|
static void Destroy(std::string source = "", bool log = true);
|
||||||
|
|
||||||
static void Connect(dConfig* config);
|
static sql::Statement* CreateStmt();
|
||||||
static void Destroy();
|
static sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
||||||
|
static void Commit();
|
||||||
|
static bool GetAutoCommit();
|
||||||
|
static void SetAutoCommit(bool value);
|
||||||
|
|
||||||
|
static std::string GetDatabase() { return database; }
|
||||||
|
static sql::Properties GetProperties() { return props; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
set(DDATABASE_DATABASES_SOURCES "MySQL.cpp")
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "RakNetTypes.h"
|
|
||||||
|
|
||||||
#include "Structures.h"
|
|
||||||
|
|
||||||
enum eConnectionTypes {
|
|
||||||
NONE,
|
|
||||||
MYSQL,
|
|
||||||
SQLITE
|
|
||||||
};
|
|
||||||
|
|
||||||
class DatabaseBase {
|
|
||||||
public:
|
|
||||||
virtual void Connect() = 0;
|
|
||||||
virtual void Destroy() = 0;
|
|
||||||
|
|
||||||
// Server Get
|
|
||||||
virtual SocketDescriptor GetMasterServerIP() = 0;
|
|
||||||
|
|
||||||
// Server Set
|
|
||||||
virtual void CreateServer(const std::string& name, const std::string& ip, uint16_t port, uint32_t state, uint32_t version) = 0;
|
|
||||||
virtual void SetServerIpAndPortByName(const std::string& name, const std::string& ip, uint16_t port) = 0;
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
virtual void InsertIntoActivityLog(uint32_t playerId, uint32_t activityId, uint32_t timestamp, uint32_t zoneId) = 0;
|
|
||||||
virtual void InsertIntoCommandLog(uint32_t playerId, const std::string& command) = 0;
|
|
||||||
|
|
||||||
// Character Get
|
|
||||||
virtual CharacterInfo GetCharacterInfoByID(uint32_t id) = 0;
|
|
||||||
virtual CharacterInfo GetCharacterInfoByName(const std::string& name) = 0;
|
|
||||||
virtual std::string GetCharacterXMLByID(uint32_t id) = 0;
|
|
||||||
virtual std::vector<std::string> GetAllCharacterNames() = 0;
|
|
||||||
virtual std::vector<CharacterInfo> GetAllCharactersByAccountID(uint32_t accountId) = 0;
|
|
||||||
virtual bool IsCharacterNameAvailable(const std::string& name) = 0;
|
|
||||||
|
|
||||||
// Charater Write
|
|
||||||
virtual void CreateCharacterXML(uint32_t id, const std::string& xml) = 0;
|
|
||||||
virtual void UpdateCharacterXML(uint32_t id, const std::string& xml) = 0;
|
|
||||||
virtual void CreateCharacter(uint32_t id, uint32_t account_id, const std::string& name, const std::string& pending_name, bool needs_rename, uint64_t last_login) = 0;
|
|
||||||
virtual void ApproveCharacterName(uint32_t id, const std::string& newName) = 0;
|
|
||||||
virtual void SetPendingCharacterName(uint32_t id, const std::string& pendingName) = 0;
|
|
||||||
virtual void UpdateCharacterLastLogin(uint32_t id, uint64_t time) = 0;
|
|
||||||
|
|
||||||
// Character Delete
|
|
||||||
virtual void DeleteCharacter(uint32_t id) = 0;
|
|
||||||
|
|
||||||
// Friends Get
|
|
||||||
virtual bool AreBestFriends(uint32_t charId1, uint32_t charId2) = 0;
|
|
||||||
|
|
||||||
// Account Get
|
|
||||||
virtual AccountInfo GetAccountByName(const std::string& name) = 0;
|
|
||||||
virtual AccountInfo GetAccountByID(uint32_t id) = 0;
|
|
||||||
virtual uint32_t GetLatestCharacterOfAccount(uint32_t id) = 0;
|
|
||||||
|
|
||||||
// Account Set
|
|
||||||
virtual void BanAccount(uint32_t id) = 0;
|
|
||||||
virtual void MuteAccount(uint32_t id, uint64_t muteExpireDate) = 0;
|
|
||||||
|
|
||||||
// Pet Write
|
|
||||||
virtual void CreatePetName(uint64_t id, const std::string& name, bool approved) = 0;
|
|
||||||
|
|
||||||
// Pet Delete
|
|
||||||
virtual void DeletePetName(uint64_t id) = 0;
|
|
||||||
|
|
||||||
// Pet Get
|
|
||||||
virtual PetName GetPetName(uint64_t id) = 0;
|
|
||||||
|
|
||||||
// Keys Get
|
|
||||||
virtual bool IsKeyActive(uint32_t id) = 0;
|
|
||||||
|
|
||||||
// Object ID tracker Get
|
|
||||||
virtual uint32_t GetObjectIDTracker() = 0;
|
|
||||||
|
|
||||||
// Object ID tracker Set
|
|
||||||
virtual void SetObjectIDTracker(uint32_t id) = 0;
|
|
||||||
|
|
||||||
// Mail Get
|
|
||||||
virtual MailInfo GetMailByID(uint64_t id) = 0;
|
|
||||||
virtual std::vector<MailInfo> GetAllRecentMailOfUser(uint32_t id) = 0;
|
|
||||||
virtual uint32_t GetUnreadMailCountForUser(uint32_t id) = 0;
|
|
||||||
|
|
||||||
// Mail Write
|
|
||||||
virtual void WriteMail(uint32_t senderId, const std::string& senderName, uint32_t receiverId, const std::string& receiverName, uint64_t sendTime, const std::string& subject, const std::string& body, uint32_t attachmentId = 0, uint32_t attachmentLot = 0, uint64_t attachmentSubkey = 0, uint32_t attachmentCount = 0, bool wasRead = false) = 0;
|
|
||||||
virtual void SetMailAsRead(uint64_t id) = 0;
|
|
||||||
virtual void RemoveAttachmentFromMail(uint64_t id) = 0;
|
|
||||||
|
|
||||||
// Mail Delete
|
|
||||||
virtual void DeleteMail(uint64_t id) = 0;
|
|
||||||
|
|
||||||
// Property Get
|
|
||||||
virtual uint64_t GetPropertyFromTemplateAndClone(uint32_t templateId, uint32_t cloneId) = 0;
|
|
||||||
virtual std::vector<uint32_t> GetBBBModlesForProperty(uint32_t propertyId) = 0;
|
|
||||||
virtual std::istream GetLXFMLFromID(uint32_t id) = 0;
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
set(DDATABASE_DATABASES_MIGRATIONS_SOURCES "MigrationManager.cpp" "MySQLMigration.cpp")
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
#include "MigrationManager.h"
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "dLogger.h"
|
|
||||||
#include "GeneralUtils.h"
|
|
||||||
#include "CDClientDatabase.h"
|
|
||||||
#include "BinaryPathFinder.h"
|
|
||||||
|
|
||||||
Migration Migration::LoadMigration(const std::string& type, const std::string& dbType, const std::string& name) {
|
|
||||||
Migration migration{};
|
|
||||||
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / type / dbType / name);
|
|
||||||
|
|
||||||
if (file.is_open()) {
|
|
||||||
std::string line;
|
|
||||||
std::string total = "";
|
|
||||||
|
|
||||||
while (std::getline(file, line)) {
|
|
||||||
total += line;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
migration.name = ;
|
|
||||||
migration.data = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
return migration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MigrationManager::RunSQLiteMigrations() {
|
|
||||||
auto cdstmt = CDClientDatabase::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
|
||||||
cdstmt.execQuery().finalize();
|
|
||||||
cdstmt.finalize();
|
|
||||||
|
|
||||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "migrations/cdserver/").string())) {
|
|
||||||
auto migration = Migration::LoadMigration("cdserver", "", entry);
|
|
||||||
|
|
||||||
if (migration.data.empty()) continue;
|
|
||||||
|
|
||||||
// Check if there is an entry in the migration history table on the cdclient database.
|
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
|
||||||
cdstmt.bind((int32_t)1, migration.name.c_str());
|
|
||||||
auto cdres = cdstmt.execQuery();
|
|
||||||
bool doExit = !cdres.eof();
|
|
||||||
cdres.finalize();
|
|
||||||
cdstmt.finalize();
|
|
||||||
|
|
||||||
if (doExit) continue;
|
|
||||||
|
|
||||||
// Check first if there is entry in the migration history table on the main database.
|
|
||||||
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
|
||||||
stmt->setString(1, migration.name.c_str());
|
|
||||||
auto* res = stmt->executeQuery();
|
|
||||||
doExit = res->next();
|
|
||||||
delete res;
|
|
||||||
delete stmt;
|
|
||||||
if (doExit) {
|
|
||||||
// Insert into cdclient database if there is an entry in the main database but not the cdclient database.
|
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
|
||||||
cdstmt.bind((int32_t)1, migration.name.c_str());
|
|
||||||
cdstmt.execQuery().finalize();
|
|
||||||
cdstmt.finalize();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doing these 1 migration at a time since one takes a long time and some may think it is crashing.
|
|
||||||
// This will at the least guarentee that the full migration needs to be run in order to be counted as "migrated".
|
|
||||||
Game::logger->Log("MigrationRunner", "Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str());
|
|
||||||
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
|
|
||||||
for (const auto& dml : GeneralUtils::SplitString(migration.data, ';')) {
|
|
||||||
if (dml.empty()) continue;
|
|
||||||
try {
|
|
||||||
CDClientDatabase::ExecuteDML(dml.c_str());
|
|
||||||
} catch (CppSQLite3Exception& e) {
|
|
||||||
Game::logger->Log("MigrationRunner", "Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert into cdclient database.
|
|
||||||
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
|
||||||
cdstmt.bind((int32_t)1, migration.name.c_str());
|
|
||||||
cdstmt.execQuery().finalize();
|
|
||||||
cdstmt.finalize();
|
|
||||||
CDClientDatabase::ExecuteQuery("COMMIT;");
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::logger->Log("MigrationRunner", "CDServer database is up to date.");
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class DatabaseBase;
|
|
||||||
|
|
||||||
struct Migration {
|
|
||||||
std::string data;
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
static Migration LoadMigration(const std::string& type, const std::string& dbType, const std::string& name);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MigrationManager {
|
|
||||||
public:
|
|
||||||
void RunMigrations(DatabaseBase* db);
|
|
||||||
void RunSQLiteMigrations();
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "MigrationManager.h"
|
|
||||||
|
|
||||||
class MySQLMigrationManager : public MigrationManager {
|
|
||||||
public:
|
|
||||||
void RunMigrations(DatabaseBase* db) override;
|
|
||||||
void RunSQLiteMigrations() override;
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -1,651 +0,0 @@
|
|||||||
#include "MySQL.h"
|
|
||||||
|
|
||||||
#pragma warning (disable:4251)
|
|
||||||
|
|
||||||
#include "Game.h"
|
|
||||||
#include "dConfig.h"
|
|
||||||
#include "dLogger.h"
|
|
||||||
|
|
||||||
MySQLDatabase::MySQLDatabase(const std::string& host, const std::string& database, const std::string& username, const std::string& password) {
|
|
||||||
this->m_Host = host;
|
|
||||||
this->m_Database = database;
|
|
||||||
this->m_Username = username;
|
|
||||||
this->m_Password = password;
|
|
||||||
|
|
||||||
m_Driver = sql::mariadb::get_driver_instance();
|
|
||||||
|
|
||||||
sql::Properties properties;
|
|
||||||
|
|
||||||
// The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where
|
|
||||||
// 1) it tries to parse a database from the connection string (like in tcp://localhost:3001/darkflame) based on the
|
|
||||||
// presence of a /
|
|
||||||
// 2) even avoiding that, the connector still assumes you're connecting with a tcp socket
|
|
||||||
// So, what we do in the presence of a unix socket or pipe is to set the hostname to the protocol and localhost,
|
|
||||||
// which avoids parsing errors while still ensuring the correct connection type is used, and then setting the appropriate
|
|
||||||
// property manually (which the URL parsing fails to do)
|
|
||||||
const std::string UNIX_PROTO = "unix://";
|
|
||||||
const std::string PIPE_PROTO = "pipe://";
|
|
||||||
if (this->m_Host.find(UNIX_PROTO) == 0) {
|
|
||||||
properties["hostName"] = "unix://localhost";
|
|
||||||
properties["localSocket"] = this->m_Host.substr(UNIX_PROTO.length()).c_str();
|
|
||||||
} else if (this->m_Host.find(PIPE_PROTO) == 0) {
|
|
||||||
properties["hostName"] = "pipe://localhost";
|
|
||||||
properties["pipe"] = this->m_Host.substr(PIPE_PROTO.length()).c_str();
|
|
||||||
} else {
|
|
||||||
properties["hostName"] = this->m_Host.c_str();
|
|
||||||
}
|
|
||||||
properties["user"] = this->m_Username.c_str();
|
|
||||||
properties["password"] = this->m_Password.c_str();
|
|
||||||
properties["autoReconnect"] = "true";
|
|
||||||
|
|
||||||
this->m_Properties = properties;
|
|
||||||
this->m_Database = database;
|
|
||||||
}
|
|
||||||
|
|
||||||
MySQLDatabase::~MySQLDatabase() {
|
|
||||||
this->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::Connect() {
|
|
||||||
if (this->m_Properties.find("localSocket") != this->m_Properties.end() || this->m_Properties.find("pipe") != this->m_Properties.end()) {
|
|
||||||
this->m_Connection = m_Driver->connect(this->m_Properties);
|
|
||||||
} else {
|
|
||||||
this->m_Connection = m_Driver->connect(
|
|
||||||
this->m_Properties["hostName"].c_str(),
|
|
||||||
this->m_Properties["user"].c_str(),
|
|
||||||
this->m_Properties["password"].c_str()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this->m_Connection->setSchema(this->m_Database.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::Destroy() {
|
|
||||||
if (this->m_Connection != nullptr) {
|
|
||||||
this->m_Connection->close();
|
|
||||||
delete this->m_Connection;
|
|
||||||
this->m_Connection = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sql::Statement* MySQLDatabase::CreateStmt() {
|
|
||||||
sql::Statement* toReturn = this->m_Connection->createStatement();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
sql::PreparedStatement* MySQLDatabase::CreatePreppedStmt(const std::string& query) {
|
|
||||||
const char* test = query.c_str();
|
|
||||||
size_t size = query.length();
|
|
||||||
sql::SQLString str(test, size);
|
|
||||||
|
|
||||||
if (!this->m_Connection) {
|
|
||||||
Connect();
|
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this->m_Connection->isValid() || this->m_Connection->isClosed()) {
|
|
||||||
delete this->m_Connection;
|
|
||||||
|
|
||||||
this->m_Connection = nullptr;
|
|
||||||
|
|
||||||
Connect();
|
|
||||||
Game::logger->Log("Database", "Trying to reconnect to MySQL from invalid or closed connection");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* stmt = this->m_Connection->prepareStatement(str);
|
|
||||||
|
|
||||||
return stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> MySQLDatabase::CreatePreppedStmtUnique(const std::string& query) {
|
|
||||||
std::unique_ptr<sql::PreparedStatement> stmt(CreatePreppedStmt(query));
|
|
||||||
return stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<sql::ResultSet> MySQLDatabase::GetResultsOfStatement(sql::Statement* stmt) {
|
|
||||||
auto* res = stmt->executeQuery();
|
|
||||||
std::unique_ptr<sql::ResultSet> result(res);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MySQLDatabase::Commit() {
|
|
||||||
this->m_Connection->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySQLDatabase::GetAutoCommit() {
|
|
||||||
// TODO This should not just access a pointer. A future PR should update this
|
|
||||||
// to check for null and throw an error if the connection is not valid.
|
|
||||||
return m_Connection->getAutoCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SetAutoCommit(bool value) {
|
|
||||||
// TODO This should not just access a pointer. A future PR should update this
|
|
||||||
// to check for null and throw an error if the connection is not valid.
|
|
||||||
m_Connection->setAutoCommit(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketDescriptor MySQLDatabase::GetMasterServerIP() {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT ip, port FROM servers WHERE name = 'master';");
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return SocketDescriptor(res->getInt("port"), res->getString("ip"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return SocketDescriptor(0, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::CreateServer(const std::string& name, const std::string& ip, uint16_t port, uint32_t state, uint32_t version) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO servers (name, ip, port, state, version) VALUES (?, ?, ?, ?, ?);");
|
|
||||||
stmt->setString(1, name);
|
|
||||||
stmt->setString(2, ip);
|
|
||||||
stmt->setInt(3, port);
|
|
||||||
stmt->setInt(4, state);
|
|
||||||
stmt->setInt(5, version);
|
|
||||||
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SetServerIpAndPortByName(const std::string& name, const std::string& ip, uint16_t port) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE servers SET ip = ?, port = ? WHERE name = ?;");
|
|
||||||
stmt->setString(1, ip);
|
|
||||||
stmt->setInt(2, port);
|
|
||||||
stmt->setString(3, name);
|
|
||||||
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> MySQLDatabase::GetAllCharacterNames() {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT name FROM charinfo;");
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
std::vector<std::string> names;
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
names.push_back(res->getString("name").c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySQLDatabase::IsCharacterNameAvailable(const std::string& name) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT name FROM charinfo WHERE name = ? OR pending_name = ?;");
|
|
||||||
stmt->setString(1, name);
|
|
||||||
stmt->setString(2, name);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
return !res->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::InsertIntoActivityLog(uint32_t playerId, uint32_t activityId, uint32_t timestamp, uint32_t zoneId) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
|
||||||
|
|
||||||
stmt->setUInt(1, playerId);
|
|
||||||
stmt->setUInt(2, activityId);
|
|
||||||
stmt->setUInt(3, timestamp);
|
|
||||||
stmt->setUInt(4, zoneId);
|
|
||||||
|
|
||||||
stmt->executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::InsertIntoCommandLog(uint32_t playerId, const std::string& command) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO command_log (character_id, command) VALUES (?, ?);");
|
|
||||||
|
|
||||||
stmt->setUInt(1, playerId);
|
|
||||||
stmt->setString(2, command);
|
|
||||||
|
|
||||||
stmt->executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
CharacterInfo MySQLDatabase::GetCharacterInfoByID(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT account_id, name, pending_name, needs_rename, prop_clone_id, permission_map FROM charinfo WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
CharacterInfo info{};
|
|
||||||
info.AccountID = res->getUInt("account_id");
|
|
||||||
info.ID = id;
|
|
||||||
info.Name = res->getString("name");
|
|
||||||
info.PendingName = res->getString("pending_name");
|
|
||||||
info.NameRejected = res->getBoolean("needs_rename");
|
|
||||||
info.PropertyCloneID = res->getUInt("prop_clone_id");
|
|
||||||
info.PermissionMap = (ePermissionMap)res->getUInt("permission_map");
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CharacterInfo{};
|
|
||||||
}
|
|
||||||
|
|
||||||
CharacterInfo MySQLDatabase::GetCharacterInfoByName(const std::string& name) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT id FROM charinfo WHERE name = ?");
|
|
||||||
stmt->setString(1, name);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return GetCharacterInfoByID(res->getUInt("id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return CharacterInfo{};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetLatestCharacterOfAccount(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT id FROM charinfo WHERE account_id = ? ORDER BY last_login DESC LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return res->getUInt("id");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string MySQLDatabase::GetCharacterXMLByID(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT xml_data FROM charxml WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return res->getString("xml_data").c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::CreateCharacterXML(uint32_t id, const std::string& xml) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO charxml (id, xml_data) VALUES (?, ?);");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->setString(2, xml);
|
|
||||||
|
|
||||||
stmt->executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::UpdateCharacterXML(uint32_t id, const std::string& xml) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE charxml SET xml_data = ? WHERE id = ?;");
|
|
||||||
stmt->setString(1, xml);
|
|
||||||
stmt->setUInt(2, id);
|
|
||||||
|
|
||||||
stmt->executeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::CreateCharacter(uint32_t id, uint32_t account_id, const std::string& name, const std::string& pending_name, bool needs_rename, uint64_t last_login) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO charinfo (id, account_id, name, pending_name, needs_rename, last_login) VALUES (?, ?, ?, ?, ?, ?);");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->setUInt(2, account_id);
|
|
||||||
stmt->setString(3, name);
|
|
||||||
stmt->setString(4, pending_name);
|
|
||||||
stmt->setBoolean(5, needs_rename);
|
|
||||||
stmt->setUInt64(6, last_login);
|
|
||||||
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::ApproveCharacterName(uint32_t id, const std::string& newName) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE charinfo SET name = ?, pending_name = '', needs_rename = 0, last_login = ? WHERE id = ? LIMIT 1");
|
|
||||||
stmt->setString(1, newName);
|
|
||||||
stmt->setUInt64(2, time(NULL));
|
|
||||||
stmt->setUInt(3, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SetPendingCharacterName(uint32_t id, const std::string& pendingName) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE charinfo SET pending_name=?, needs_rename=0, last_login=? WHERE id=? LIMIT 1;");
|
|
||||||
stmt->setString(1, pendingName);
|
|
||||||
stmt->setUInt64(2, time(NULL));
|
|
||||||
stmt->setUInt(3, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::UpdateCharacterLastLogin(uint32_t id, uint64_t time) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE charinfo SET last_login = ? WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt64(1, time);
|
|
||||||
stmt->setUInt(2, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::DeleteCharacter(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("DELETE FROM charxml WHERE id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM command_log WHERE character_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM friends WHERE player_id = ? OR friend_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->setUInt(2, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM leaderboard WHERE character_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM properties_contents WHERE property_id IN (SELECT id FROM properties WHERE owner_id = ?)");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM properties WHERE owner_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM ugc WHERE character_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM activity_log WHERE character_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM mail WHERE receiver_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
stmt = CreatePreppedStmtUnique("DELETE FROM charinfo WHERE id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
AccountInfo MySQLDatabase::GetAccountByName(const std::string& name) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT id FROM accounts WHERE name = ? LIMIT 1;");
|
|
||||||
stmt->setString(1, name);
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return GetAccountByID(res->getUInt("id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return AccountInfo{};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySQLDatabase::AreBestFriends(uint32_t goon1, uint32_t goon2) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;");
|
|
||||||
stmt->setUInt(1, goon1);
|
|
||||||
stmt->setUInt(2, goon2);
|
|
||||||
stmt->setUInt(3, goon2);
|
|
||||||
stmt->setUInt(4, goon1);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return res->getInt("best_friend") == 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
AccountInfo MySQLDatabase::GetAccountByID(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT name, password, gm_level, locked, banned, play_key_id, created_at, mute_expire FROM accounts WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
AccountInfo info{};
|
|
||||||
info.ID = id;
|
|
||||||
info.Name = res->getString("name");
|
|
||||||
info.Password = res->getString("password");
|
|
||||||
info.MaxGMLevel = res->getUInt("gm_level");
|
|
||||||
info.Locked = res->getBoolean("locked");
|
|
||||||
info.Banned = res->getBoolean("banned");
|
|
||||||
info.PlayKeyID = res->getUInt("play_key_id");
|
|
||||||
info.CreatedAt = res->getUInt64("created_at");
|
|
||||||
info.MuteExpire = res->getUInt64("mute_expire");
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AccountInfo{};
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::BanAccount(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE accounts SET banned = 1 WHERE id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::MuteAccount(uint32_t id, uint64_t muteExpireDate) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE accounts SET mute_expire = ? WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, muteExpireDate);
|
|
||||||
stmt->setUInt(2, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CharacterInfo> MySQLDatabase::GetAllCharactersByAccountID(uint32_t accountId) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT id FROM charinfo WHERE account_id = ? LIMIT 4;");
|
|
||||||
stmt->setUInt(1, accountId);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
std::vector<CharacterInfo> characters;
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
characters.push_back(GetCharacterInfoByID(res->getUInt("id")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return characters;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::CreatePetName(uint64_t id, const std::string& name, bool approved) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO pet_names (id, name, approved) VALUES (?, ?, ?);");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
stmt->setString(2, name);
|
|
||||||
stmt->setBoolean(3, approved);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::DeletePetName(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("DELETE FROM pet_names WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
PetName MySQLDatabase::GetPetName(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT name, approved FROM pet_names WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
PetName name{};
|
|
||||||
name.ID = id;
|
|
||||||
name.Name = res->getString("name");
|
|
||||||
name.Approved = res->getBoolean("approved");
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PetName{};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySQLDatabase::IsKeyActive(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT * FROM play_keys WHERE id = ? AND active = 1 LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetObjectIDTracker() {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT last_object_id FROM object_id_tracker;");
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
uint32_t id = res->getUInt("last_object_id");
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO object_id_tracker (last_object_id) VALUES (1);");
|
|
||||||
stmt->execute();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SetObjectIDTracker(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE object_id_tracker SET last_object_id = ?;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
MailInfo MySQLDatabase::GetMailByID(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT * FROM mail WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
if (res->next()) {
|
|
||||||
MailInfo mail{};
|
|
||||||
mail.ID = id;
|
|
||||||
mail.SenderID = res->getUInt("sender_id");
|
|
||||||
mail.SenderName = res->getString("sender_name");
|
|
||||||
mail.ReceiverID = res->getUInt("receiver_id");
|
|
||||||
mail.ReceiverName = res->getString("receiver_name");
|
|
||||||
mail.TimeSent = res->getUInt64("time_sent");
|
|
||||||
mail.Subject = res->getString("subject");
|
|
||||||
mail.Body = res->getString("body");
|
|
||||||
mail.AttachmentID = res->getUInt("attachment_id");
|
|
||||||
mail.AttachmentLOT = res->getUInt("attachment_lot");
|
|
||||||
mail.AttachmentSubkey = res->getUInt64("attachment_subkey");
|
|
||||||
mail.AttachmentCount = res->getUInt("attachment_count");
|
|
||||||
mail.WasRead = res->getBoolean("was_read");
|
|
||||||
|
|
||||||
return mail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MailInfo{};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MailInfo> MySQLDatabase::GetAllRecentMailOfUser(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT * FROM mail WHERE receiver_id = ? LIMIT 20;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
std::vector<MailInfo> mail;
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
MailInfo mailInfo{};
|
|
||||||
mailInfo.ID = res->getUInt64("id");
|
|
||||||
mailInfo.SenderID = res->getUInt("sender_id");
|
|
||||||
mailInfo.SenderName = res->getString("sender_name");
|
|
||||||
mailInfo.ReceiverID = res->getUInt("receiver_id");
|
|
||||||
mailInfo.ReceiverName = res->getString("receiver_name");
|
|
||||||
mailInfo.TimeSent = res->getUInt64("time_sent");
|
|
||||||
mailInfo.Subject = res->getString("subject");
|
|
||||||
mailInfo.Body = res->getString("body");
|
|
||||||
mailInfo.AttachmentID = res->getUInt("attachment_id");
|
|
||||||
mailInfo.AttachmentLOT = res->getUInt("attachment_lot");
|
|
||||||
mailInfo.AttachmentSubkey = res->getUInt64("attachment_subkey");
|
|
||||||
mailInfo.AttachmentCount = res->getUInt("attachment_count");
|
|
||||||
mailInfo.WasRead = res->getBoolean("was_read");
|
|
||||||
|
|
||||||
mail.push_back(mailInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mail;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MySQLDatabase::GetUnreadMailCountForUser(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT COUNT(*) FROM mail WHERE receiver_id = ? AND was_read = 0;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return res->getUInt(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::WriteMail(uint32_t senderId, const std::string& senderName, uint32_t receiverId, const std::string& receiverName, uint64_t sendTime, const std::string& subject, const std::string& body, uint32_t attachmentId, uint32_t attachmentLot, uint64_t attachmentSubkey, uint32_t attachmentCount, bool wasRead) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("INSERT INTO mail (sender_id, sender_name, receiver_id, receiver_name, time_sent, subject, body, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);");
|
|
||||||
stmt->setUInt(1, senderId);
|
|
||||||
stmt->setString(2, senderName);
|
|
||||||
stmt->setUInt(3, receiverId);
|
|
||||||
stmt->setString(4, receiverName);
|
|
||||||
stmt->setUInt64(5, sendTime);
|
|
||||||
stmt->setString(6, subject);
|
|
||||||
stmt->setString(7, body);
|
|
||||||
stmt->setUInt(8, attachmentId);
|
|
||||||
stmt->setUInt(9, attachmentLot);
|
|
||||||
stmt->setUInt64(10, attachmentSubkey);
|
|
||||||
stmt->setUInt(11, attachmentCount);
|
|
||||||
stmt->setBoolean(12, wasRead);
|
|
||||||
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::DeleteMail(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("DELETE FROM mail WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::SetMailAsRead(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE mail SET was_read = 1 WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MySQLDatabase::RemoveAttachmentFromMail(uint64_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("UPDATE mail SET attachment_lot = 0 WHERE id = ?;");
|
|
||||||
stmt->setUInt64(1, id);
|
|
||||||
stmt->execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t MySQLDatabase::GetPropertyFromTemplateAndClone(uint32_t templateId, uint32_t cloneId) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT id FROM properties WHERE template_id = ? AND clone_id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt(1, templateId);
|
|
||||||
stmt->setUInt(2, cloneId);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
return res->getUInt64("id");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint32_t> MySQLDatabase::GetBBBModlesForProperty(uint32_t propertyId) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT ugc_id FROM properties_contents WHERE lot = 14 AND property_id = ?;");
|
|
||||||
stmt->setUInt(1, propertyId);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
std::vector<uint32_t> models;
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
models.push_back(res->getUInt("ugc_id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream* MySQLDatabase::GetLXFMLFromID(uint32_t id) {
|
|
||||||
auto stmt = CreatePreppedStmtUnique("SELECT lxfml FROM ugc WHERE id = ? LIMIT 1;");
|
|
||||||
stmt->setUInt(1, id);
|
|
||||||
|
|
||||||
auto res = GetResultsOfStatement(stmt.get());
|
|
||||||
|
|
||||||
while (res->next()) {
|
|
||||||
std::istream* blob = res->getBlob("lxfml");
|
|
||||||
return blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new std::istream();
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DatabaseBase.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <conncpp.hpp>
|
|
||||||
|
|
||||||
class MySqlException : public std::runtime_error {
|
|
||||||
public:
|
|
||||||
MySqlException() : std::runtime_error("MySQL error!") {}
|
|
||||||
MySqlException(const std::string& msg) : std::runtime_error(msg.c_str()) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MySQLDatabase : public DatabaseBase {
|
|
||||||
public:
|
|
||||||
MySQLDatabase(const std::string& host, const std::string& database, const std::string& username, const std::string& password);
|
|
||||||
~MySQLDatabase();
|
|
||||||
|
|
||||||
void Connect() override;
|
|
||||||
void Destroy() override;
|
|
||||||
|
|
||||||
sql::Statement* CreateStmt();
|
|
||||||
sql::PreparedStatement* CreatePreppedStmt(const std::string& query);
|
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> CreatePreppedStmtUnique(const std::string& query);
|
|
||||||
std::unique_ptr<sql::ResultSet> GetResultsOfStatement(sql::Statement* stmt);
|
|
||||||
|
|
||||||
void Commit();
|
|
||||||
bool GetAutoCommit();
|
|
||||||
void SetAutoCommit(bool value);
|
|
||||||
|
|
||||||
SocketDescriptor GetMasterServerIP() override;
|
|
||||||
|
|
||||||
void CreateServer(const std::string& name, const std::string& ip, uint16_t port, uint32_t state, uint32_t version) override;
|
|
||||||
void SetServerIpAndPortByName(const std::string& name, const std::string& ip, uint16_t port) override;
|
|
||||||
|
|
||||||
void InsertIntoActivityLog(uint32_t playerId, uint32_t activityId, uint32_t timestamp, uint32_t zoneId) override;
|
|
||||||
void InsertIntoCommandLog(uint32_t playerId, const std::string& command) override;
|
|
||||||
|
|
||||||
CharacterInfo GetCharacterInfoByID(uint32_t id) override;
|
|
||||||
CharacterInfo GetCharacterInfoByName(const std::string& name) override;
|
|
||||||
std::string GetCharacterXMLByID(uint32_t id) override;
|
|
||||||
std::vector<std::string> GetAllCharacterNames() override;
|
|
||||||
std::vector<CharacterInfo> GetAllCharactersByAccountID(uint32_t accountId) override;
|
|
||||||
bool IsCharacterNameAvailable(const std::string& name) override;
|
|
||||||
|
|
||||||
void CreateCharacterXML(uint32_t id, const std::string& xml) override;
|
|
||||||
void UpdateCharacterXML(uint32_t id, const std::string& xml) override;
|
|
||||||
void CreateCharacter(uint32_t id, uint32_t account_id, const std::string& name, const std::string& pending_name, bool needs_rename, uint64_t last_login) override;
|
|
||||||
void ApproveCharacterName(uint32_t id, const std::string& newName) override;
|
|
||||||
void SetPendingCharacterName(uint32_t id, const std::string& pendingName) override;
|
|
||||||
void UpdateCharacterLastLogin(uint32_t id, uint64_t time) override;
|
|
||||||
|
|
||||||
void DeleteCharacter(uint32_t id) override;
|
|
||||||
|
|
||||||
bool AreBestFriends(uint32_t charId1, uint32_t charId2) override;
|
|
||||||
|
|
||||||
AccountInfo GetAccountByName(const std::string& name) override;
|
|
||||||
AccountInfo GetAccountByID(uint32_t id) override;
|
|
||||||
uint32_t GetLatestCharacterOfAccount(uint32_t id) override;
|
|
||||||
|
|
||||||
void BanAccount(uint32_t id) override;
|
|
||||||
void MuteAccount(uint32_t id, uint64_t muteExpireDate) override;
|
|
||||||
|
|
||||||
void CreatePetName(uint64_t id, const std::string& name, bool approved) override;
|
|
||||||
|
|
||||||
void DeletePetName(uint64_t id) override;
|
|
||||||
|
|
||||||
PetName GetPetName(uint64_t id) override;
|
|
||||||
|
|
||||||
bool IsKeyActive(uint32_t id) override;
|
|
||||||
|
|
||||||
uint32_t GetObjectIDTracker() override;
|
|
||||||
|
|
||||||
void SetObjectIDTracker(uint32_t id) override;
|
|
||||||
|
|
||||||
MailInfo GetMailByID(uint64_t id) override;
|
|
||||||
std::vector<MailInfo> GetAllRecentMailOfUser(uint32_t id) override;
|
|
||||||
uint32_t GetUnreadMailCountForUser(uint32_t id) override;
|
|
||||||
|
|
||||||
void WriteMail(uint32_t senderId, const std::string& senderName, uint32_t receiverId, const std::string& receiverName, uint64_t sendTime, const std::string& subject, const std::string& body, uint32_t attachmentId = 0, uint32_t attachmentLot = 0, uint64_t attachmentSubkey = 0, uint32_t attachmentCount = 0, bool wasRead = false) override;
|
|
||||||
void SetMailAsRead(uint64_t id) override;
|
|
||||||
void RemoveAttachmentFromMail(uint64_t id) override;
|
|
||||||
|
|
||||||
void DeleteMail(uint64_t id) override;
|
|
||||||
|
|
||||||
uint64_t GetPropertyFromTemplateAndClone(uint32_t templateId, uint32_t cloneId) override;
|
|
||||||
std::vector<uint32_t> GetBBBModlesForProperty(uint32_t propertyId) override;
|
|
||||||
std::istream GetLXFMLFromID(uint32_t id) override;
|
|
||||||
private:
|
|
||||||
std::string m_Host;
|
|
||||||
std::string m_Database;
|
|
||||||
std::string m_Username;
|
|
||||||
std::string m_Password;
|
|
||||||
|
|
||||||
sql::Connection* m_Connection;
|
|
||||||
sql::Driver* m_Driver;
|
|
||||||
sql::Properties m_Properties;
|
|
||||||
};
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "ePermissionMap.h"
|
|
||||||
|
|
||||||
struct CharacterInfo {
|
|
||||||
uint32_t AccountID;
|
|
||||||
uint32_t ID;
|
|
||||||
std::string Name;
|
|
||||||
std::string PendingName;
|
|
||||||
bool NameRejected;
|
|
||||||
uint32_t PropertyCloneID;
|
|
||||||
ePermissionMap PermissionMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AccountInfo {
|
|
||||||
uint32_t ID;
|
|
||||||
std::string Name;
|
|
||||||
std::string Password;
|
|
||||||
uint32_t MaxGMLevel;
|
|
||||||
bool Locked;
|
|
||||||
bool Banned;
|
|
||||||
uint32_t PlayKeyID;
|
|
||||||
uint64_t CreatedAt;
|
|
||||||
uint64_t MuteExpire;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PetName {
|
|
||||||
uint64_t ID;
|
|
||||||
std::string Name;
|
|
||||||
bool Approved;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MailInfo {
|
|
||||||
uint64_t ID;
|
|
||||||
uint32_t SenderID;
|
|
||||||
std::string SenderName;
|
|
||||||
uint32_t ReceiverID;
|
|
||||||
std::string ReceiverName;
|
|
||||||
uint64_t TimeSent;
|
|
||||||
std::string Subject;
|
|
||||||
std::string Body;
|
|
||||||
uint32_t AttachmentID;
|
|
||||||
uint32_t AttachmentLOT;
|
|
||||||
uint64_t AttachmentSubkey;
|
|
||||||
uint32_t AttachmentCount;
|
|
||||||
bool WasRead;
|
|
||||||
};
|
|
||||||
158
dDatabase/MigrationRunner.cpp
Normal file
158
dDatabase/MigrationRunner.cpp
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include "MigrationRunner.h"
|
||||||
|
|
||||||
|
#include "BrickByBrickFix.h"
|
||||||
|
#include "CDClientDatabase.h"
|
||||||
|
#include "Database.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "BinaryPathFinder.h"
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
Migration LoadMigration(std::string path) {
|
||||||
|
Migration migration{};
|
||||||
|
std::ifstream file(BinaryPathFinder::GetBinaryDir() / "migrations/" / path);
|
||||||
|
|
||||||
|
if (file.is_open()) {
|
||||||
|
std::string line;
|
||||||
|
std::string total = "";
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
total += line;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
migration.name = path;
|
||||||
|
migration.data = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
return migration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MigrationRunner::RunMigrations() {
|
||||||
|
auto* stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
||||||
|
stmt->execute();
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
|
sql::SQLString finalSQL = "";
|
||||||
|
bool runSd0Migrations = false;
|
||||||
|
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/").string())) {
|
||||||
|
auto migration = LoadMigration("dlu/" + entry);
|
||||||
|
|
||||||
|
if (migration.data.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
|
stmt->setString(1, migration.name.c_str());
|
||||||
|
auto* res = stmt->executeQuery();
|
||||||
|
bool doExit = res->next();
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
if (doExit) continue;
|
||||||
|
|
||||||
|
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
||||||
|
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
||||||
|
runSd0Migrations = true;
|
||||||
|
} else {
|
||||||
|
finalSQL.append(migration.data.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt = Database::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
|
stmt->setString(1, migration.name.c_str());
|
||||||
|
stmt->execute();
|
||||||
|
delete stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalSQL.empty() && !runSd0Migrations) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Server database is up to date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!finalSQL.empty()) {
|
||||||
|
auto migration = GeneralUtils::SplitString(static_cast<std::string>(finalSQL), ';');
|
||||||
|
std::unique_ptr<sql::Statement> simpleStatement(Database::CreateStmt());
|
||||||
|
for (auto& query : migration) {
|
||||||
|
try {
|
||||||
|
if (query.empty()) continue;
|
||||||
|
simpleStatement->execute(query.c_str());
|
||||||
|
} catch (sql::SQLException& e) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Encountered error running migration: %s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do this last on the off chance none of the other migrations have been run yet.
|
||||||
|
if (runSd0Migrations) {
|
||||||
|
uint32_t numberOfUpdatedModels = BrickByBrickFix::UpdateBrickByBrickModelsToSd0();
|
||||||
|
Game::logger->Log("MasterServer", "%i models were updated from zlib to sd0.", numberOfUpdatedModels);
|
||||||
|
uint32_t numberOfTruncatedModels = BrickByBrickFix::TruncateBrokenBrickByBrickXml();
|
||||||
|
Game::logger->Log("MasterServer", "%i models were truncated from the database.", numberOfTruncatedModels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MigrationRunner::RunSQLiteMigrations() {
|
||||||
|
auto cdstmt = CDClientDatabase::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);");
|
||||||
|
cdstmt.execQuery().finalize();
|
||||||
|
cdstmt.finalize();
|
||||||
|
|
||||||
|
auto* stmt = Database::CreatePreppedStmt("CREATE TABLE IF NOT EXISTS migration_history (name TEXT NOT NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP());");
|
||||||
|
stmt->execute();
|
||||||
|
delete stmt;
|
||||||
|
|
||||||
|
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "migrations/cdserver/").string())) {
|
||||||
|
auto migration = LoadMigration("cdserver/" + entry);
|
||||||
|
|
||||||
|
if (migration.data.empty()) continue;
|
||||||
|
|
||||||
|
// Check if there is an entry in the migration history table on the cdclient database.
|
||||||
|
cdstmt = CDClientDatabase::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
|
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
||||||
|
auto cdres = cdstmt.execQuery();
|
||||||
|
bool doExit = !cdres.eof();
|
||||||
|
cdres.finalize();
|
||||||
|
cdstmt.finalize();
|
||||||
|
|
||||||
|
if (doExit) continue;
|
||||||
|
|
||||||
|
// Check first if there is entry in the migration history table on the main database.
|
||||||
|
stmt = Database::CreatePreppedStmt("SELECT name FROM migration_history WHERE name = ?;");
|
||||||
|
stmt->setString(1, migration.name.c_str());
|
||||||
|
auto* res = stmt->executeQuery();
|
||||||
|
doExit = res->next();
|
||||||
|
delete res;
|
||||||
|
delete stmt;
|
||||||
|
if (doExit) {
|
||||||
|
// Insert into cdclient database if there is an entry in the main database but not the cdclient database.
|
||||||
|
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
|
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
||||||
|
cdstmt.execQuery().finalize();
|
||||||
|
cdstmt.finalize();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doing these 1 migration at a time since one takes a long time and some may think it is crashing.
|
||||||
|
// This will at the least guarentee that the full migration needs to be run in order to be counted as "migrated".
|
||||||
|
Game::logger->Log("MigrationRunner", "Executing migration: %s. This may take a while. Do not shut down server.", migration.name.c_str());
|
||||||
|
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
|
||||||
|
for (const auto& dml : GeneralUtils::SplitString(migration.data, ';')) {
|
||||||
|
if (dml.empty()) continue;
|
||||||
|
try {
|
||||||
|
CDClientDatabase::ExecuteDML(dml.c_str());
|
||||||
|
} catch (CppSQLite3Exception& e) {
|
||||||
|
Game::logger->Log("MigrationRunner", "Encountered error running DML command: (%i) : %s", e.errorCode(), e.errorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert into cdclient database.
|
||||||
|
cdstmt = CDClientDatabase::CreatePreppedStmt("INSERT INTO migration_history (name) VALUES (?);");
|
||||||
|
cdstmt.bind((int32_t) 1, migration.name.c_str());
|
||||||
|
cdstmt.execQuery().finalize();
|
||||||
|
cdstmt.finalize();
|
||||||
|
CDClientDatabase::ExecuteQuery("COMMIT;");
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::logger->Log("MigrationRunner", "CDServer database is up to date.");
|
||||||
|
}
|
||||||
13
dDatabase/MigrationRunner.h
Normal file
13
dDatabase/MigrationRunner.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct Migration {
|
||||||
|
std::string data;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace MigrationRunner {
|
||||||
|
void RunMigrations();
|
||||||
|
void RunSQLiteMigrations();
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
void CDActivitiesTable::LoadValuesFromDatabase() {
|
CDActivitiesTable::CDActivitiesTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Activities");
|
||||||
@@ -54,3 +55,8 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CDActivities> CDActivitiesTable::GetEntries(void) const {
|
||||||
|
return this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,9 @@ private:
|
|||||||
std::vector<CDActivities> entries;
|
std::vector<CDActivities> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDActivitiesTable();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
||||||
|
|
||||||
const std::vector<CDActivities>& GetEntries() const { return this->entries; }
|
std::vector<CDActivities> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDActivityRewardsTable.h"
|
#include "CDActivityRewardsTable.h"
|
||||||
|
|
||||||
void CDActivityRewardsTable::LoadValuesFromDatabase() {
|
CDActivityRewardsTable::CDActivityRewardsTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,3 +43,8 @@ std::vector<CDActivityRewards> CDActivityRewardsTable::Query(std::function<bool(
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CDActivityRewards> CDActivityRewardsTable::GetEntries(void) const {
|
||||||
|
return this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ private:
|
|||||||
std::vector<CDActivityRewards> entries;
|
std::vector<CDActivityRewards> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDActivityRewardsTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
||||||
|
|
||||||
std::vector<CDActivityRewards> GetEntries() const;
|
std::vector<CDActivityRewards> GetEntries(void) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,35 +2,6 @@
|
|||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
|
||||||
void CDAnimationsTable::LoadValuesFromDatabase() {
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
std::string animation_type = tableData.getStringField("animation_type", "");
|
|
||||||
DluAssert(!animation_type.empty());
|
|
||||||
AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1);
|
|
||||||
DluAssert(animationGroupID != -1);
|
|
||||||
|
|
||||||
CDAnimation entry;
|
|
||||||
entry.animation_name = tableData.getStringField("animation_name", "");
|
|
||||||
entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f);
|
|
||||||
UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);)
|
|
||||||
UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);)
|
|
||||||
entry.animation_length = tableData.getFloatField("animation_length", 0.0f);
|
|
||||||
UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;)
|
|
||||||
UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;)
|
|
||||||
UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;)
|
|
||||||
UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");)
|
|
||||||
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
|
|
||||||
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
|
|
||||||
|
|
||||||
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
|
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
|
bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
|
||||||
auto tableData = queryToCache.execQuery();
|
auto tableData = queryToCache.execQuery();
|
||||||
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ class CDAnimationsTable : public CDTable<CDAnimationsTable> {
|
|||||||
typedef std::string AnimationID;
|
typedef std::string AnimationID;
|
||||||
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
|
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
|
||||||
/**
|
/**
|
||||||
* Given an animationType and the previousAnimationName played, return the next animationType to play.
|
* Given an animationType and the previousAnimationName played, return the next animationType to play.
|
||||||
* If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow
|
* If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
#include "CDBehaviorParameterTable.h"
|
#include "CDBehaviorParameterTable.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
|
CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
|
||||||
uint64_t key = behaviorID;
|
|
||||||
key <<= 31U;
|
|
||||||
key |= parameterID;
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
||||||
|
uint32_t uniqueParameterId = 0;
|
||||||
|
uint64_t hash = 0;
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
|
CDBehaviorParameter entry;
|
||||||
|
entry.behaviorID = tableData.getIntField("behaviorID", -1);
|
||||||
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
|
||||||
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
auto parameter = m_ParametersList.find(candidateStringToAdd);
|
||||||
uint32_t parameterId;
|
|
||||||
if (parameter != m_ParametersList.end()) {
|
if (parameter != m_ParametersList.end()) {
|
||||||
parameterId = parameter->second;
|
entry.parameterID = parameter;
|
||||||
} else {
|
} else {
|
||||||
parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
|
entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first;
|
||||||
|
uniqueParameterId++;
|
||||||
}
|
}
|
||||||
uint64_t hash = GetKey(behaviorID, parameterId);
|
hash = entry.behaviorID;
|
||||||
float value = tableData.getFloatField("value", -1.0f);
|
hash = (hash << 31U) | entry.parameterID->second;
|
||||||
|
entry.value = tableData.getFloatField("value", -1.0f);
|
||||||
|
|
||||||
m_Entries.insert(std::make_pair(hash, value));
|
m_Entries.insert(std::make_pair(hash, entry));
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
@@ -34,22 +30,27 @@ void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
|||||||
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
|
||||||
auto parameterID = this->m_ParametersList.find(name);
|
auto parameterID = this->m_ParametersList.find(name);
|
||||||
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
if (parameterID == this->m_ParametersList.end()) return defaultValue;
|
||||||
auto hash = GetKey(behaviorID, parameterID->second);
|
|
||||||
|
uint64_t hash = behaviorID;
|
||||||
|
|
||||||
|
hash = (hash << 31U) | parameterID->second;
|
||||||
|
|
||||||
// Search for specific parameter
|
// Search for specific parameter
|
||||||
auto it = m_Entries.find(hash);
|
const auto& it = m_Entries.find(hash);
|
||||||
return it != m_Entries.end() ? it->second : defaultValue;
|
return it != m_Entries.end() ? it->second.value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
|
||||||
uint64_t hashBase = behaviorID;
|
uint64_t hashBase = behaviorID;
|
||||||
std::map<std::string, float> returnInfo;
|
std::map<std::string, float> returnInfo;
|
||||||
for (auto& [parameterString, parameterId] : m_ParametersList) {
|
uint64_t hash;
|
||||||
uint64_t hash = GetKey(hashBase, parameterId);
|
for (auto& parameterCandidate : m_ParametersList) {
|
||||||
|
hash = (hashBase << 31U) | parameterCandidate.second;
|
||||||
auto infoCandidate = m_Entries.find(hash);
|
auto infoCandidate = m_Entries.find(hash);
|
||||||
if (infoCandidate != m_Entries.end()) {
|
if (infoCandidate != m_Entries.end()) {
|
||||||
returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
|
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnInfo;
|
return returnInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,18 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct CDBehaviorParameter {
|
||||||
|
unsigned int behaviorID; //!< The Behavior ID
|
||||||
|
std::unordered_map<std::string, uint32_t>::iterator parameterID; //!< The Parameter ID
|
||||||
|
float value; //!< The value of the behavior template
|
||||||
|
};
|
||||||
|
|
||||||
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
|
||||||
private:
|
private:
|
||||||
typedef uint64_t BehaviorParameterHash;
|
std::unordered_map<uint64_t, CDBehaviorParameter> m_Entries;
|
||||||
typedef float BehaviorParameterValue;
|
|
||||||
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
|
|
||||||
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
std::unordered_map<std::string, uint32_t> m_ParametersList;
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDBehaviorParameterTable();
|
||||||
|
|
||||||
float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
float GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue = 0);
|
||||||
|
|
||||||
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);
|
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDBehaviorTemplateTable.h"
|
#include "CDBehaviorTemplateTable.h"
|
||||||
|
|
||||||
void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
|
CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -48,7 +48,7 @@ std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::Query(std::function<boo
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
|
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,3 +64,4 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav
|
|||||||
return entry->second;
|
return entry->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ private:
|
|||||||
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
std::unordered_map<uint32_t, CDBehaviorTemplate> entriesMappedByBehaviorID;
|
||||||
std::unordered_set<std::string> m_EffectHandles;
|
std::unordered_set<std::string> m_EffectHandles;
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDBehaviorTemplateTable();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
|
std::vector<CDBehaviorTemplate> Query(std::function<bool(CDBehaviorTemplate)> predicate);
|
||||||
|
|
||||||
const std::vector<CDBehaviorTemplate>& GetEntries(void) const;
|
std::vector<CDBehaviorTemplate> GetEntries(void) const;
|
||||||
|
|
||||||
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
|
const CDBehaviorTemplate GetByBehaviorID(uint32_t behaviorID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDBrickIDTableTable.h"
|
#include "CDBrickIDTableTable.h"
|
||||||
|
|
||||||
void CDBrickIDTableTable::LoadValuesFromDatabase() {
|
CDBrickIDTableTable::CDBrickIDTableTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -39,7 +39,7 @@ std::vector<CDBrickIDTable> CDBrickIDTableTable::Query(std::function<bool(CDBric
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
|
std::vector<CDBrickIDTable> CDBrickIDTableTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ private:
|
|||||||
std::vector<CDBrickIDTable> entries;
|
std::vector<CDBrickIDTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDBrickIDTableTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
||||||
|
|
||||||
const std::vector<CDBrickIDTable>& GetEntries() const;
|
std::vector<CDBrickIDTable> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
#define CDCLIENT_CACHE_ALL
|
||||||
|
|
||||||
|
CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
|
||||||
|
|
||||||
|
#ifdef CDCLIENT_CACHE_ALL
|
||||||
|
// First, get the size of the table
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ComponentsRegistry");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
//this->entries.reserve(size);
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
@@ -11,42 +29,65 @@ void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
|||||||
entry.component_id = tableData.getIntField("component_id", -1);
|
entry.component_id = tableData.getIntField("component_id", -1);
|
||||||
|
|
||||||
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
||||||
this->mappedEntries.insert_or_assign(entry.id, 0);
|
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
||||||
auto exists = mappedEntries.find(id);
|
const auto& iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
if (exists != mappedEntries.end()) {
|
|
||||||
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
if (iter == this->mappedEntries.end()) {
|
||||||
return iter == mappedEntries.end() ? defaultValue : iter->second;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now get the data. Get all components of this entity so we dont do a query for each component
|
return iter->second;
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
|
|
||||||
query.bind(1, static_cast<int32_t>(id));
|
|
||||||
|
|
||||||
auto tableData = query.execQuery();
|
#ifndef CDCLIENT_CACHE_ALL
|
||||||
|
// Now get the data
|
||||||
|
std::stringstream query;
|
||||||
|
|
||||||
|
query << "SELECT * FROM ComponentsRegistry WHERE id = " << std::to_string(id);
|
||||||
|
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDComponentsRegistry entry;
|
CDComponentsRegistry entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
|
entry.component_type = tableData.getIntField("component_type", -1);
|
||||||
entry.component_id = tableData.getIntField("component_id", -1);
|
entry.component_id = tableData.getIntField("component_id", -1);
|
||||||
|
|
||||||
this->mappedEntries.insert_or_assign(((uint64_t)entry.component_type) << 32 | ((uint64_t)entry.id), entry.component_id);
|
//this->entries.push_back(entry);
|
||||||
|
|
||||||
|
//Darwin's stuff:
|
||||||
|
const auto& it = this->mappedEntries.find(entry.id);
|
||||||
|
if (it != mappedEntries.end()) {
|
||||||
|
const auto& iter = it->second.find(entry.component_type);
|
||||||
|
if (iter == it->second.end()) {
|
||||||
|
it->second.insert(std::make_pair(entry.component_type, entry.component_id));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::map<unsigned int, unsigned int> map;
|
||||||
|
map.insert(std::make_pair(entry.component_type, entry.component_id));
|
||||||
|
this->mappedEntries.insert(std::make_pair(entry.id, map));
|
||||||
|
}
|
||||||
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
mappedEntries.insert_or_assign(id, 0);
|
tableData.finalize();
|
||||||
|
|
||||||
auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
const auto& it2 = this->mappedEntries.find(id);
|
||||||
|
if (it2 != mappedEntries.end()) {
|
||||||
|
const auto& iter = it2->second.find(componentType);
|
||||||
|
if (iter != it2->second.end()) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return iter == this->mappedEntries.end() ? defaultValue : iter->second;
|
return defaultValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ struct CDComponentsRegistry {
|
|||||||
|
|
||||||
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDComponentsRegistryTable();
|
||||||
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CDCurrencyTableTable.h"
|
#include "CDCurrencyTableTable.h"
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
void CDCurrencyTableTable::LoadValuesFromDatabase() {
|
CDCurrencyTableTable::CDCurrencyTableTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,7 +43,7 @@ std::vector<CDCurrencyTable> CDCurrencyTableTable::Query(std::function<bool(CDCu
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
|
std::vector<CDCurrencyTable> CDCurrencyTableTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ private:
|
|||||||
std::vector<CDCurrencyTable> entries;
|
std::vector<CDCurrencyTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDCurrencyTableTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
||||||
|
|
||||||
const std::vector<CDCurrencyTable>& GetEntries() const;
|
std::vector<CDCurrencyTable> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "CDDestructibleComponentTable.h"
|
#include "CDDestructibleComponentTable.h"
|
||||||
|
|
||||||
void CDDestructibleComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDDestructibleComponentTable::CDDestructibleComponentTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM DestructibleComponent");
|
||||||
@@ -50,7 +52,7 @@ std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::fu
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
|
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ private:
|
|||||||
std::vector<CDDestructibleComponent> entries;
|
std::vector<CDDestructibleComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDDestructibleComponentTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
||||||
|
|
||||||
const std::vector<CDDestructibleComponent>& GetEntries(void) const;
|
std::vector<CDDestructibleComponent> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,26 +1,40 @@
|
|||||||
#include "CDEmoteTable.h"
|
#include "CDEmoteTable.h"
|
||||||
|
|
||||||
void CDEmoteTableTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDEmoteTableTable::CDEmoteTableTable(void) {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDEmoteTable entry;
|
CDEmoteTable* entry = new CDEmoteTable();
|
||||||
entry.ID = tableData.getIntField("id", -1);
|
entry->ID = tableData.getIntField("id", -1);
|
||||||
entry.animationName = tableData.getStringField("animationName", "");
|
entry->animationName = tableData.getStringField("animationName", "");
|
||||||
entry.iconFilename = tableData.getStringField("iconFilename", "");
|
entry->iconFilename = tableData.getStringField("iconFilename", "");
|
||||||
entry.channel = tableData.getIntField("channel", -1);
|
entry->channel = tableData.getIntField("channel", -1);
|
||||||
entry.locked = tableData.getIntField("locked", -1) != 0;
|
entry->locked = tableData.getIntField("locked", -1) != 0;
|
||||||
entry.localize = tableData.getIntField("localize", -1) != 0;
|
entry->localize = tableData.getIntField("localize", -1) != 0;
|
||||||
entry.locState = tableData.getIntField("locStatus", -1);
|
entry->locState = tableData.getIntField("locStatus", -1);
|
||||||
entry.gateVersion = tableData.getStringField("gate_version", "");
|
entry->gateVersion = tableData.getStringField("gate_version", "");
|
||||||
|
|
||||||
entries.insert(std::make_pair(entry.ID, entry));
|
entries.insert(std::make_pair(entry->ID, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
//! Destructor
|
||||||
auto itr = entries.find(id);
|
CDEmoteTableTable::~CDEmoteTableTable(void) {
|
||||||
return itr != entries.end() ? &itr->second : nullptr;
|
for (auto e : entries) {
|
||||||
|
if (e.second) delete e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
||||||
|
for (auto e : entries) {
|
||||||
|
if (e.first == id) return e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ struct CDEmoteTable {
|
|||||||
|
|
||||||
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> {
|
class CDEmoteTableTable : public CDTable<CDEmoteTableTable> {
|
||||||
private:
|
private:
|
||||||
std::map<int, CDEmoteTable> entries;
|
std::map<int, CDEmoteTable*> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDEmoteTableTable();
|
||||||
|
~CDEmoteTableTable();
|
||||||
// Returns an emote by ID
|
// Returns an emote by ID
|
||||||
CDEmoteTable* GetEmote(int id);
|
CDEmoteTable* GetEmote(int id);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDFeatureGatingTable.h"
|
#include "CDFeatureGatingTable.h"
|
||||||
|
|
||||||
void CDFeatureGatingTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDFeatureGatingTable::CDFeatureGatingTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -52,7 +53,7 @@ bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
|
std::vector<CDFeatureGating> CDFeatureGatingTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ private:
|
|||||||
std::vector<CDFeatureGating> entries;
|
std::vector<CDFeatureGating> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDFeatureGatingTable();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
|
std::vector<CDFeatureGating> Query(std::function<bool(CDFeatureGating)> predicate);
|
||||||
|
|
||||||
bool FeatureUnlocked(const std::string& feature) const;
|
bool FeatureUnlocked(const std::string& feature) const;
|
||||||
|
|
||||||
const std::vector<CDFeatureGating>& GetEntries(void) const;
|
std::vector<CDFeatureGating> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDInventoryComponentTable.h"
|
#include "CDInventoryComponentTable.h"
|
||||||
|
|
||||||
void CDInventoryComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDInventoryComponentTable::CDInventoryComponentTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -41,7 +42,7 @@ std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
|
std::vector<CDInventoryComponent> CDInventoryComponentTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ private:
|
|||||||
std::vector<CDInventoryComponent> entries;
|
std::vector<CDInventoryComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDInventoryComponentTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
||||||
|
|
||||||
const std::vector<CDInventoryComponent>& GetEntries() const;
|
std::vector<CDInventoryComponent> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
CDItemComponent CDItemComponentTable::Default = {};
|
CDItemComponent CDItemComponentTable::Default = {};
|
||||||
|
|
||||||
void CDItemComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDItemComponentTable::CDItemComponentTable(void) {
|
||||||
|
Default = CDItemComponent();
|
||||||
|
|
||||||
|
#ifdef CDCLIENT_CACHE_ALL
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ItemComponent");
|
||||||
@@ -51,13 +55,13 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
|
|||||||
entry.currencyLOT = tableData.getIntField("currencyLOT", -1);
|
entry.currencyLOT = tableData.getIntField("currencyLOT", -1);
|
||||||
entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1);
|
entry.altCurrencyCost = tableData.getIntField("altCurrencyCost", -1);
|
||||||
entry.subItems = tableData.getStringField("subItems", "");
|
entry.subItems = tableData.getStringField("subItems", "");
|
||||||
UNUSED_COLUMN(entry.audioEventUse = tableData.getStringField("audioEventUse", ""));
|
entry.audioEventUse = tableData.getStringField("audioEventUse", "");
|
||||||
entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false;
|
entry.noEquipAnimation = tableData.getIntField("noEquipAnimation", -1) == 1 ? true : false;
|
||||||
entry.commendationLOT = tableData.getIntField("commendationLOT", -1);
|
entry.commendationLOT = tableData.getIntField("commendationLOT", -1);
|
||||||
entry.commendationCost = tableData.getIntField("commendationCost", -1);
|
entry.commendationCost = tableData.getIntField("commendationCost", -1);
|
||||||
UNUSED_COLUMN(entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", ""));
|
entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", "");
|
||||||
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
||||||
UNUSED_COLUMN(entry.ingredientInfo = tableData.getStringField("ingredientInfo", ""));
|
entry.ingredientInfo = tableData.getStringField("ingredientInfo", "");
|
||||||
entry.locStatus = tableData.getIntField("locStatus", -1);
|
entry.locStatus = tableData.getIntField("locStatus", -1);
|
||||||
entry.forgeType = tableData.getIntField("forgeType", -1);
|
entry.forgeType = tableData.getIntField("forgeType", -1);
|
||||||
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
|
entry.SellMultiplier = tableData.getFloatField("SellMultiplier", -1.0f);
|
||||||
@@ -67,6 +71,7 @@ void CDItemComponentTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
||||||
@@ -75,10 +80,12 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;");
|
#ifndef CDCLIENT_CACHE_ALL
|
||||||
query.bind(1, static_cast<int32_t>(skillID));
|
std::stringstream query;
|
||||||
|
|
||||||
auto tableData = query.execQuery();
|
query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(skillID);
|
||||||
|
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
||||||
if (tableData.eof()) {
|
if (tableData.eof()) {
|
||||||
entries.insert(std::make_pair(skillID, Default));
|
entries.insert(std::make_pair(skillID, Default));
|
||||||
return Default;
|
return Default;
|
||||||
@@ -137,6 +144,7 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
|
|||||||
if (it2 != this->entries.end()) {
|
if (it2 != this->entries.end()) {
|
||||||
return it2->second;
|
return it2->second;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return Default;
|
return Default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ private:
|
|||||||
std::map<unsigned int, CDItemComponent> entries;
|
std::map<unsigned int, CDItemComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDItemComponentTable();
|
||||||
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
|
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
|
||||||
|
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDItemSetSkillsTable.h"
|
#include "CDItemSetSkillsTable.h"
|
||||||
|
|
||||||
void CDItemSetSkillsTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDItemSetSkillsTable::CDItemSetSkillsTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -40,7 +41,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDIt
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
|
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ private:
|
|||||||
std::vector<CDItemSetSkills> entries;
|
std::vector<CDItemSetSkills> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDItemSetSkillsTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
||||||
|
|
||||||
const std::vector<CDItemSetSkills>& GetEntries() const;
|
std::vector<CDItemSetSkills> GetEntries(void) const;
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDItemSetsTable.h"
|
#include "CDItemSetsTable.h"
|
||||||
|
|
||||||
void CDItemSetsTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDItemSetsTable::CDItemSetsTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -52,7 +53,7 @@ std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> p
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
|
std::vector<CDItemSets> CDItemSetsTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ private:
|
|||||||
std::vector<CDItemSets> entries;
|
std::vector<CDItemSets> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDItemSetsTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
||||||
|
|
||||||
const std::vector<CDItemSets>& GetEntries(void) const;
|
std::vector<CDItemSets> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDLevelProgressionLookupTable.h"
|
#include "CDLevelProgressionLookupTable.h"
|
||||||
|
|
||||||
void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -31,6 +32,7 @@ void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Queries the table with a custom "where" clause
|
||||||
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
|
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::function<bool(CDLevelProgressionLookup)> predicate) {
|
||||||
|
|
||||||
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries)
|
std::vector<CDLevelProgressionLookup> data = cpplinq::from(this->entries)
|
||||||
@@ -40,7 +42,8 @@ std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
|
//! Gets all the entries in the table
|
||||||
|
std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ private:
|
|||||||
std::vector<CDLevelProgressionLookup> entries;
|
std::vector<CDLevelProgressionLookup> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDLevelProgressionLookupTable();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
||||||
|
|
||||||
const std::vector<CDLevelProgressionLookup>& GetEntries() const;
|
// Gets all the entries in the table
|
||||||
|
std::vector<CDLevelProgressionLookup> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,7 @@
|
|||||||
#include "CDLootMatrixTable.h"
|
#include "CDLootMatrixTable.h"
|
||||||
|
|
||||||
CDLootMatrix CDLootMatrixTable::ReadRow(CppSQLite3Query& tableData) const {
|
//! Constructor
|
||||||
CDLootMatrix entry{};
|
CDLootMatrixTable::CDLootMatrixTable(void) {
|
||||||
if (tableData.eof()) return entry;
|
|
||||||
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
|
||||||
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
|
||||||
entry.percent = tableData.getFloatField("percent", -1.0f);
|
|
||||||
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
|
||||||
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
|
||||||
entry.flagID = tableData.getIntField("flagID", -1);
|
|
||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDLootMatrixTable::LoadValuesFromDatabase() {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -24,6 +12,8 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -31,28 +21,33 @@ void CDLootMatrixTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootMatrix entry;
|
CDLootMatrix entry;
|
||||||
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
|
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
entry.RarityTableIndex = tableData.getIntField("RarityTableIndex", -1);
|
||||||
|
entry.percent = tableData.getFloatField("percent", -1.0f);
|
||||||
|
entry.minToDrop = tableData.getIntField("minToDrop", -1);
|
||||||
|
entry.maxToDrop = tableData.getIntField("maxToDrop", -1);
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.flagID = tableData.getIntField("flagID", -1);
|
||||||
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
|
|
||||||
this->entries[lootMatrixIndex].push_back(ReadRow(tableData));
|
this->entries.push_back(entry);
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LootMatrixEntries& CDLootMatrixTable::GetMatrix(uint32_t matrixId) {
|
|
||||||
auto itr = this->entries.find(matrixId);
|
|
||||||
if (itr != this->entries.end()) {
|
|
||||||
return itr->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootMatrix where LootMatrixIndex = ?;");
|
|
||||||
query.bind(1, static_cast<int32_t>(matrixId));
|
|
||||||
|
|
||||||
auto tableData = query.execQuery();
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
this->entries[matrixId].push_back(ReadRow(tableData));
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->entries[matrixId];
|
tableData.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CDLootMatrix> CDLootMatrixTable::Query(std::function<bool(CDLootMatrix)> predicate) {
|
||||||
|
|
||||||
|
std::vector<CDLootMatrix> data = cpplinq::from(this->entries)
|
||||||
|
>> cpplinq::where(predicate)
|
||||||
|
>> cpplinq::to_vector();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries(void) const {
|
||||||
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,26 +4,26 @@
|
|||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
struct CDLootMatrix {
|
struct CDLootMatrix {
|
||||||
|
unsigned int LootMatrixIndex; //!< The Loot Matrix Index
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
unsigned int RarityTableIndex; //!< The Rarity Table Index
|
||||||
float percent; //!< The percent that this matrix is used?
|
float percent; //!< The percent that this matrix is used?
|
||||||
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
unsigned int minToDrop; //!< The minimum amount of loot from this matrix to drop
|
||||||
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
unsigned int maxToDrop; //!< The maximum amount of loot from this matrix to drop
|
||||||
|
unsigned int id; //!< The ID of the Loot Matrix
|
||||||
unsigned int flagID; //!< ???
|
unsigned int flagID; //!< ???
|
||||||
UNUSED(std::string gate_version); //!< The Gate Version
|
UNUSED(std::string gate_version); //!< The Gate Version
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t LootMatrixIndex;
|
|
||||||
typedef std::vector<CDLootMatrix> LootMatrixEntries;
|
|
||||||
|
|
||||||
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
class CDLootMatrixTable : public CDTable<CDLootMatrixTable> {
|
||||||
public:
|
|
||||||
void LoadValuesFromDatabase();
|
|
||||||
|
|
||||||
// Gets a matrix by ID or inserts a blank one if none existed.
|
|
||||||
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
|
|
||||||
private:
|
private:
|
||||||
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
|
std::vector<CDLootMatrix> entries;
|
||||||
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
|
|
||||||
|
public:
|
||||||
|
CDLootMatrixTable();
|
||||||
|
// Queries the table with a custom "where" clause
|
||||||
|
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
|
||||||
|
|
||||||
|
const std::vector<CDLootMatrix>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
#include "CDLootTableTable.h"
|
#include "CDLootTableTable.h"
|
||||||
|
|
||||||
CDLootTable CDLootTableTable::ReadRow(CppSQLite3Query& tableData) const {
|
//! Constructor
|
||||||
CDLootTable entry{};
|
CDLootTableTable::CDLootTableTable(void) {
|
||||||
if (tableData.eof()) return entry;
|
|
||||||
entry.itemid = tableData.getIntField("itemid", -1);
|
|
||||||
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
|
||||||
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDLootTableTable::LoadValuesFromDatabase() {
|
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -20,6 +12,8 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
tableSize.nextRow();
|
tableSize.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tableSize.finalize();
|
||||||
|
|
||||||
// Reserve the size
|
// Reserve the size
|
||||||
this->entries.reserve(size);
|
this->entries.reserve(size);
|
||||||
|
|
||||||
@@ -27,28 +21,32 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootTable entry;
|
CDLootTable entry;
|
||||||
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.itemid = tableData.getIntField("itemid", -1);
|
||||||
|
entry.LootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.MissionDrop = tableData.getIntField("MissionDrop", -1) == 1 ? true : false;
|
||||||
|
entry.sortPriority = tableData.getIntField("sortPriority", -1);
|
||||||
|
|
||||||
this->entries[lootTableIndex].push_back(ReadRow(tableData));
|
this->entries.push_back(entry);
|
||||||
tableData.nextRow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
|
|
||||||
auto itr = this->entries.find(tableId);
|
|
||||||
if (itr != this->entries.end()) {
|
|
||||||
return itr->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM LootTable WHERE LootTableIndex = ?;");
|
|
||||||
query.bind(1, static_cast<int32_t>(tableId));
|
|
||||||
auto tableData = query.execQuery();
|
|
||||||
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
CDLootTable entry;
|
|
||||||
this->entries[tableId].push_back(ReadRow(tableData));
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->entries[tableId];
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Queries the table with a custom "where" clause
|
||||||
|
std::vector<CDLootTable> CDLootTableTable::Query(std::function<bool(CDLootTable)> predicate) {
|
||||||
|
|
||||||
|
std::vector<CDLootTable> data = cpplinq::from(this->entries)
|
||||||
|
>> cpplinq::where(predicate)
|
||||||
|
>> cpplinq::to_vector();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Gets all the entries in the table
|
||||||
|
const std::vector<CDLootTable>& CDLootTableTable::GetEntries(void) const {
|
||||||
|
return this->entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,20 @@
|
|||||||
struct CDLootTable {
|
struct CDLootTable {
|
||||||
unsigned int itemid; //!< The LOT of the item
|
unsigned int itemid; //!< The LOT of the item
|
||||||
unsigned int LootTableIndex; //!< The Loot Table Index
|
unsigned int LootTableIndex; //!< The Loot Table Index
|
||||||
|
unsigned int id; //!< The ID
|
||||||
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
bool MissionDrop; //!< Whether or not this loot table is a mission drop
|
||||||
unsigned int sortPriority; //!< The sorting priority
|
unsigned int sortPriority; //!< The sorting priority
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t LootTableIndex;
|
|
||||||
typedef std::vector<CDLootTable> LootTableEntries;
|
|
||||||
|
|
||||||
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
class CDLootTableTable : public CDTable<CDLootTableTable> {
|
||||||
private:
|
private:
|
||||||
CDLootTable ReadRow(CppSQLite3Query& tableData) const;
|
std::vector<CDLootTable> entries;
|
||||||
std::unordered_map<LootTableIndex, LootTableEntries> entries;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDLootTableTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
const LootTableEntries& GetTable(uint32_t tableId);
|
std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate);
|
||||||
|
|
||||||
|
const std::vector<CDLootTable>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDMissionEmailTable.h"
|
#include "CDMissionEmailTable.h"
|
||||||
|
|
||||||
void CDMissionEmailTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDMissionEmailTable::CDMissionEmailTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -47,7 +48,7 @@ std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMiss
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
|
std::vector<CDMissionEmail> CDMissionEmailTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ private:
|
|||||||
std::vector<CDMissionEmail> entries;
|
std::vector<CDMissionEmail> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDMissionEmailTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
||||||
|
|
||||||
const std::vector<CDMissionEmail>& GetEntries() const;
|
std::vector<CDMissionEmail> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDMissionNPCComponentTable.h"
|
#include "CDMissionNPCComponentTable.h"
|
||||||
|
|
||||||
void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDMissionNPCComponentTable::CDMissionNPCComponentTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -44,7 +45,7 @@ std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::functi
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
|
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ private:
|
|||||||
std::vector<CDMissionNPCComponent> entries;
|
std::vector<CDMissionNPCComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDMissionNPCComponentTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDMissionNPCComponent>& GetEntries() const;
|
std::vector<CDMissionNPCComponent> GetEntries(void) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDMissionTasksTable.h"
|
#include "CDMissionTasksTable.h"
|
||||||
|
|
||||||
void CDMissionTasksTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDMissionTasksTable::CDMissionTasksTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -55,14 +56,16 @@ std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missio
|
|||||||
|
|
||||||
for (auto& entry : this->entries) {
|
for (auto& entry : this->entries) {
|
||||||
if (entry.id == missionID) {
|
if (entry.id == missionID) {
|
||||||
tasks.push_back(&entry);
|
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
|
||||||
|
|
||||||
|
tasks.push_back(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const {
|
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ private:
|
|||||||
std::vector<CDMissionTasks> entries;
|
std::vector<CDMissionTasks> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDMissionTasksTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
||||||
|
|
||||||
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
|
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
|
||||||
|
|
||||||
const std::vector<CDMissionTasks>& GetEntries() const;
|
const std::vector<CDMissionTasks>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
CDMissions CDMissionsTable::Default = {};
|
CDMissions CDMissionsTable::Default = {};
|
||||||
|
|
||||||
void CDMissionsTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDMissionsTable::CDMissionsTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ private:
|
|||||||
std::vector<CDMissions> entries;
|
std::vector<CDMissions> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDMissionsTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDMissions>& GetEntries() const;
|
const std::vector<CDMissions>& GetEntries(void) const;
|
||||||
|
|
||||||
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDMovementAIComponentTable.h"
|
#include "CDMovementAIComponentTable.h"
|
||||||
|
|
||||||
void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -36,6 +37,7 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Queries the table with a custom "where" clause
|
||||||
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
||||||
|
|
||||||
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries)
|
std::vector<CDMovementAIComponent> data = cpplinq::from(this->entries)
|
||||||
@@ -45,7 +47,8 @@ std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::functi
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
|
//! Gets all the entries in the table
|
||||||
|
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ private:
|
|||||||
std::vector<CDMovementAIComponent> entries;
|
std::vector<CDMovementAIComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDMovementAIComponentTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDMovementAIComponent>& GetEntries() const;
|
std::vector<CDMovementAIComponent> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDObjectSkillsTable.h"
|
#include "CDObjectSkillsTable.h"
|
||||||
|
|
||||||
void CDObjectSkillsTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDObjectSkillsTable::CDObjectSkillsTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -32,6 +33,7 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
|
|||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Queries the table with a custom "where" clause
|
||||||
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
||||||
|
|
||||||
std::vector<CDObjectSkills> data = cpplinq::from(this->entries)
|
std::vector<CDObjectSkills> data = cpplinq::from(this->entries)
|
||||||
@@ -41,6 +43,7 @@ std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObje
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
|
//! Gets all the entries in the table
|
||||||
|
std::vector<CDObjectSkills> CDObjectSkillsTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ private:
|
|||||||
std::vector<CDObjectSkills> entries;
|
std::vector<CDObjectSkills> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDObjectSkillsTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDObjectSkills>& GetEntries() const;
|
std::vector<CDObjectSkills> GetEntries(void) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "CDObjectsTable.h"
|
#include "CDObjectsTable.h"
|
||||||
|
|
||||||
void CDObjectsTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDObjectsTable::CDObjectsTable(void) {
|
||||||
|
#ifdef CDCLIENT_CACHE_ALL
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects");
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Objects");
|
||||||
@@ -18,24 +20,25 @@ void CDObjectsTable::LoadValuesFromDatabase() {
|
|||||||
CDObjects entry;
|
CDObjects entry;
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.name = tableData.getStringField("name", "");
|
entry.name = tableData.getStringField("name", "");
|
||||||
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
|
entry.placeable = tableData.getIntField("placeable", -1);
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
UNUSED_COLUMN(entry.description = tableData.getStringField("description", "");)
|
entry.description = tableData.getStringField("description", "");
|
||||||
UNUSED_COLUMN(entry.localize = tableData.getIntField("localize", -1);)
|
entry.localize = tableData.getIntField("localize", -1);
|
||||||
UNUSED_COLUMN(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);)
|
entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);
|
||||||
UNUSED_COLUMN(entry.displayName = tableData.getStringField("displayName", "");)
|
entry.displayName = tableData.getStringField("displayName", "");
|
||||||
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
||||||
UNUSED_COLUMN(entry.nametag = tableData.getIntField("nametag", -1);)
|
entry.nametag = tableData.getIntField("nametag", -1);
|
||||||
UNUSED_COLUMN(entry._internalNotes = tableData.getStringField("_internalNotes", "");)
|
entry._internalNotes = tableData.getStringField("_internalNotes", "");
|
||||||
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1);)
|
entry.locStatus = tableData.getIntField("locStatus", -1);
|
||||||
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
|
entry.gate_version = tableData.getStringField("gate_version", "");
|
||||||
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
|
entry.HQ_valid = tableData.getIntField("HQ_valid", -1);
|
||||||
|
|
||||||
this->entries.insert(std::make_pair(entry.id, entry));
|
this->entries.insert(std::make_pair(entry.id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_default.id = 0;
|
m_default.id = 0;
|
||||||
}
|
}
|
||||||
@@ -46,10 +49,12 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
|
#ifndef CDCLIENT_CACHE_ALL
|
||||||
query.bind(1, static_cast<int32_t>(LOT));
|
std::stringstream query;
|
||||||
|
|
||||||
auto tableData = query.execQuery();
|
query << "SELECT * FROM Objects WHERE id = " << std::to_string(LOT);
|
||||||
|
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
|
||||||
if (tableData.eof()) {
|
if (tableData.eof()) {
|
||||||
this->entries.insert(std::make_pair(LOT, m_default));
|
this->entries.insert(std::make_pair(LOT, m_default));
|
||||||
return m_default;
|
return m_default;
|
||||||
@@ -83,6 +88,7 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
|
|||||||
if (it2 != entries.end()) {
|
if (it2 != entries.end()) {
|
||||||
return it2->second;
|
return it2->second;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return m_default;
|
return m_default;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ private:
|
|||||||
CDObjects m_default;
|
CDObjects m_default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDObjectsTable();
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
const CDObjects& GetByID(unsigned int LOT);
|
const CDObjects& GetByID(unsigned int LOT);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "CDPackageComponentTable.h"
|
#include "CDPackageComponentTable.h"
|
||||||
|
|
||||||
void CDPackageComponentTable::LoadValuesFromDatabase() {
|
//! Constructor
|
||||||
|
CDPackageComponentTable::CDPackageComponentTable(void) {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -42,7 +43,7 @@ std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
|
std::vector<CDPackageComponent> CDPackageComponentTable::GetEntries(void) const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ private:
|
|||||||
std::vector<CDPackageComponent> entries;
|
std::vector<CDPackageComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDPackageComponentTable(void);
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
||||||
|
|
||||||
const std::vector<CDPackageComponent>& GetEntries() const;
|
std::vector<CDPackageComponent> GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,35 +1,46 @@
|
|||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
void CDPhysicsComponentTable::LoadValuesFromDatabase() {
|
CDPhysicsComponentTable::CDPhysicsComponentTable(void) {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDPhysicsComponent entry;
|
CDPhysicsComponent* entry = new CDPhysicsComponent();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry->id = tableData.getIntField("id", -1);
|
||||||
entry.bStatic = tableData.getIntField("static", -1) != 0;
|
entry->bStatic = tableData.getIntField("static", -1) != 0;
|
||||||
entry.physicsAsset = tableData.getStringField("physics_asset", "");
|
entry->physicsAsset = tableData.getStringField("physics_asset", "");
|
||||||
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
||||||
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
||||||
entry.speed = tableData.getFloatField("speed", -1);
|
entry->speed = tableData.getFloatField("speed", -1);
|
||||||
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
||||||
entry.playerHeight = tableData.getFloatField("playerHeight");
|
entry->playerHeight = tableData.getFloatField("playerHeight");
|
||||||
entry.playerRadius = tableData.getFloatField("playerRadius");
|
entry->playerRadius = tableData.getFloatField("playerRadius");
|
||||||
entry.pcShapeType = tableData.getIntField("pcShapeType");
|
entry->pcShapeType = tableData.getIntField("pcShapeType");
|
||||||
entry.collisionGroup = tableData.getIntField("collisionGroup");
|
entry->collisionGroup = tableData.getIntField("collisionGroup");
|
||||||
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
||||||
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
||||||
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
||||||
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
||||||
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
||||||
|
|
||||||
m_entries.insert(std::make_pair(entry.id, entry));
|
m_entries.insert(std::make_pair(entry->id, entry));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
|
CDPhysicsComponentTable::~CDPhysicsComponentTable() {
|
||||||
auto itr = m_entries.find(componentID);
|
for (auto e : m_entries) {
|
||||||
return itr != m_entries.end() ? &itr->second : nullptr;
|
if (e.second) delete e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
|
||||||
|
for (auto e : m_entries) {
|
||||||
|
if (e.first == componentID) return e.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ struct CDPhysicsComponent {
|
|||||||
|
|
||||||
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDPhysicsComponentTable();
|
||||||
|
~CDPhysicsComponentTable();
|
||||||
|
|
||||||
static const std::string GetTableName() { return "PhysicsComponent"; };
|
static const std::string GetTableName() { return "PhysicsComponent"; };
|
||||||
CDPhysicsComponent* GetByID(unsigned int componentID);
|
CDPhysicsComponent* GetByID(unsigned int componentID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<unsigned int, CDPhysicsComponent> m_entries;
|
std::map<unsigned int, CDPhysicsComponent*> m_entries;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "CDPropertyEntranceComponentTable.h"
|
#include "CDPropertyEntranceComponentTable.h"
|
||||||
|
|
||||||
void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
|
CDPropertyEntranceComponentTable::CDPropertyEntranceComponentTable() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ struct CDPropertyEntranceComponent {
|
|||||||
|
|
||||||
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> {
|
class CDPropertyEntranceComponentTable : public CDTable<CDPropertyEntranceComponentTable> {
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDPropertyEntranceComponentTable();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
CDPropertyEntranceComponent GetByID(uint32_t id);
|
CDPropertyEntranceComponent GetByID(uint32_t id);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
[[nodiscard]] const std::vector<CDPropertyEntranceComponent>& GetEntries() const { return entries; }
|
[[nodiscard]] std::vector<CDPropertyEntranceComponent> GetEntries() const { return entries; }
|
||||||
private:
|
private:
|
||||||
std::vector<CDPropertyEntranceComponent> entries{};
|
std::vector<CDPropertyEntranceComponent> entries{};
|
||||||
CDPropertyEntranceComponent defaultEntry{};
|
CDPropertyEntranceComponent defaultEntry{};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDPropertyTemplateTable.h"
|
#include "CDPropertyTemplateTable.h"
|
||||||
|
|
||||||
void CDPropertyTemplateTable::LoadValuesFromDatabase() {
|
CDPropertyTemplateTable::CDPropertyTemplateTable() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ struct CDPropertyTemplate {
|
|||||||
|
|
||||||
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> {
|
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> {
|
||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
CDPropertyTemplateTable();
|
||||||
|
|
||||||
static const std::string GetTableName() { return "PropertyTemplate"; };
|
static const std::string GetTableName() { return "PropertyTemplate"; };
|
||||||
CDPropertyTemplate GetByMapID(uint32_t mapID);
|
CDPropertyTemplate GetByMapID(uint32_t mapID);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user