mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 12:04:27 -06:00
Compare commits
125 Commits
aggregate-
...
saving-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a4f310d89 | ||
| 3d85f6639e | |||
|
|
731b828c12 | ||
|
|
eca87c7257 | ||
|
|
0b9dbaedbf | ||
| 7de07a7722 | |||
|
|
62a1e135c3 | ||
|
|
de0b560a8c | ||
| e8a0f50ec9 | |||
| b3564cb9ea | |||
|
|
3df3552467 | ||
|
|
a1f8ab763d | ||
|
|
0c32be01ba | ||
|
|
8a15906885 | ||
|
|
af70f871cb | ||
|
|
fd20baaf09 | ||
|
|
0217f88c44 | ||
|
|
198b3371c5 | ||
|
|
4e5facd0c5 | ||
|
|
c931f5d456 | ||
| df83f0d847 | |||
|
|
9c5388c70e | ||
|
|
1a199151da | ||
|
|
98dc291b57 | ||
|
|
1001e41528 | ||
|
|
59bf91b14f | ||
|
|
50ad2a29ec | ||
|
|
81b1b73f04 | ||
|
|
12ea2dfb2e | ||
|
|
d193fe61be | ||
|
|
511407c8ea | ||
|
|
df3515f474 | ||
| 8e84cafdfa | |||
|
|
57e3a4f4ef | ||
|
|
98822d400f | ||
|
|
7f623d358c | ||
| b68823b4cb | |||
|
|
7bbe5ffc39 | ||
|
|
0ddd20e2b5 | ||
|
|
f59ca8b1da | ||
|
|
a44f998bd1 | ||
| 78d8c57752 | |||
|
|
8b270ca97a | ||
|
|
59303a232e | ||
| 8cd5bf7b8d | |||
| 8a9883c224 | |||
|
|
79ff6e7ee4 | ||
|
|
4167d98667 | ||
|
|
23c5d13151 | ||
|
|
68e5737b74 | ||
|
|
411dce7457 | ||
| 175b354e68 | |||
| 4c3949e5d8 | |||
| f727e3951c | |||
| 4867136133 | |||
| 6e07798023 | |||
| 3dc7b6ef7f | |||
|
|
2c9a98313a | ||
|
|
d1dc9f5403 | ||
|
|
52b5994b98 | ||
|
|
4c10faa852 | ||
|
|
070d4a1fa8 | ||
|
|
6795dd189c | ||
|
|
f40fce7711 | ||
|
|
797abb176a | ||
|
|
0f9e951162 | ||
|
|
cea0b98edf | ||
|
|
1e2d5605eb | ||
|
|
32cf111810 | ||
|
|
65c743527e | ||
| 79752c9abc | |||
|
|
01efa72aad | ||
| 6f3950dae7 | |||
|
|
a5e46e2844 | ||
|
|
3a37f9581c | ||
|
|
025ff593ce | ||
| aab60567ba | |||
|
|
9aa81f95cc | ||
|
|
5ea06f9bda | ||
|
|
ae349d6b15 | ||
|
|
22207ea9c9 | ||
|
|
23d71340c9 | ||
|
|
5942182486 | ||
|
|
131239538b | ||
|
|
4c507e34a5 | ||
|
|
50921cce2d | ||
|
|
3806891db0 | ||
|
|
ba91058736 | ||
|
|
73e70badb7 | ||
|
|
e4cae35edb | ||
|
|
2746683235 | ||
|
|
c6087ce77a | ||
|
|
e96fd56fbd | ||
|
|
500ae4d6e5 | ||
|
|
094797881b | ||
|
|
3dd2791066 | ||
| 570c597148 | |||
|
|
ad003634f4 | ||
| d8ac148cee | |||
|
|
471d65707c | ||
|
|
94f8a99fba | ||
|
|
288991ef49 | ||
|
|
74cc4176e1 | ||
| b33e9935f5 | |||
|
|
258ee5c1ee | ||
|
|
a8820c14f2 | ||
| 1ec8da8bf7 | |||
|
|
b24775f472 | ||
|
|
bd65fc6e33 | ||
|
|
44f466ac72 | ||
|
|
51540568fb | ||
| 08020cd86d | |||
| ca78a166d9 | |||
| 2e386d29df | |||
| d893ecddeb | |||
|
|
f4f13e081a | ||
|
|
c26086aff5 | ||
|
|
0337449aa7 | ||
|
|
598f4e1663 | ||
|
|
5eca25e42a | ||
|
|
d233c7e2aa | ||
| beaceb947b | |||
|
|
2cc13c6499 | ||
|
|
ad81e341da | ||
|
|
fe6be21008 |
@@ -148,17 +148,20 @@ foreach (resource_file ${RESOURCE_FILES})
|
|||||||
endforeach()
|
endforeach()
|
||||||
message(STATUS "Resource file integrity check complete")
|
message(STATUS "Resource file integrity check complete")
|
||||||
|
|
||||||
# Copy navmesh data on first build and extract it
|
# if navmeshes directory does not exist, create it
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes)
|
||||||
configure_file(
|
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/navmeshes)
|
||||||
${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip
|
|
||||||
COPYONLY
|
|
||||||
)
|
|
||||||
|
|
||||||
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip)
|
|
||||||
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Copy navmesh data on first build and extract it
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_SOURCE_DIR}/resources/navmeshes.zip ${PROJECT_BINARY_DIR}/navmeshes.zip
|
||||||
|
COPYONLY
|
||||||
|
)
|
||||||
|
|
||||||
|
file(ARCHIVE_EXTRACT INPUT ${PROJECT_BINARY_DIR}/navmeshes.zip DESTINATION ${PROJECT_BINARY_DIR}/navmeshes)
|
||||||
|
file(REMOVE ${PROJECT_BINARY_DIR}/navmeshes.zip)
|
||||||
|
|
||||||
# Copy vanity files on first build
|
# Copy vanity files on first build
|
||||||
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")
|
set(VANITY_FILES "CREDITS.md" "INFO.md" "TESTAMENT.md" "NPC.xml")
|
||||||
foreach(file ${VANITY_FILES})
|
foreach(file ${VANITY_FILES})
|
||||||
@@ -211,7 +214,12 @@ set(INCLUDED_DIRECTORIES
|
|||||||
"dNavigation/dTerrain"
|
"dNavigation/dTerrain"
|
||||||
"dZoneManager"
|
"dZoneManager"
|
||||||
"dDatabase"
|
"dDatabase"
|
||||||
"dDatabase/Tables"
|
"dDatabase/CDClientDatabase"
|
||||||
|
"dDatabase/CDClientDatabase/CDClientTables"
|
||||||
|
"dDatabase/GameDatabase"
|
||||||
|
"dDatabase/GameDatabase/ITables"
|
||||||
|
"dDatabase/GameDatabase/MySQL"
|
||||||
|
"dDatabase/GameDatabase/MySQL/Tables"
|
||||||
"dNet"
|
"dNet"
|
||||||
"dScripts"
|
"dScripts"
|
||||||
"dScripts/02_server"
|
"dScripts/02_server"
|
||||||
@@ -326,8 +334,9 @@ add_subdirectory(thirdparty)
|
|||||||
file(
|
file(
|
||||||
GLOB HEADERS_DDATABASE
|
GLOB HEADERS_DDATABASE
|
||||||
LIST_DIRECTORIES false
|
LIST_DIRECTORIES false
|
||||||
${PROJECT_SOURCE_DIR}/dDatabase/*.h
|
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/*.h
|
||||||
${PROJECT_SOURCE_DIR}/dDatabase/Tables/*.h
|
${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables/*.h
|
||||||
|
${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables/*.h
|
||||||
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h
|
${PROJECT_SOURCE_DIR}/thirdparty/SQLite/*.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=1
|
||||||
PROJECT_VERSION_PATCH=1
|
PROJECT_VERSION_PATCH=1
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
@@ -18,3 +18,5 @@ __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
|
||||||
|
|||||||
42
README.md
42
README.md
@@ -23,6 +23,9 @@ We do not recommend hosting public servers. Darkflame Universe is intended for s
|
|||||||
### Supply of resource files
|
### Supply of resource files
|
||||||
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
||||||
|
|
||||||
|
## Step by step walkthrough for a single-player server
|
||||||
|
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
||||||
|
|
||||||
## Steps to setup server
|
## Steps to setup server
|
||||||
* [Clone this repository](#clone-the-repository)
|
* [Clone this repository](#clone-the-repository)
|
||||||
* [Install dependencies](#install-dependencies)
|
* [Install dependencies](#install-dependencies)
|
||||||
@@ -224,6 +227,44 @@ sudo setcap 'cap_net_bind_service=+ep' AuthServer
|
|||||||
```
|
```
|
||||||
and then go to `build/masterconfig.ini` and change `use_sudo_auth` to 0.
|
and then go to `build/masterconfig.ini` and change `use_sudo_auth` to 0.
|
||||||
|
|
||||||
|
### Linux Service
|
||||||
|
If you are running this on a linux based system, it will use your terminal to run the program interactively, preventing you using it for other tasks and requiring it to be open to run the server.
|
||||||
|
_Note: You could use screen or tmux instead for virtual terminals_
|
||||||
|
To run the server non-interactively, we can use a systemctl service by copying the following file:
|
||||||
|
```shell
|
||||||
|
cp ./systemd.example /etc/systemd/system/darkflame.service
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure to edit the file in `/etc/systemd/system/darkflame.service` and change the:
|
||||||
|
- `User` and `Group` to the user that runs the darkflame server.
|
||||||
|
- `ExecPath` to the full file path of the server executable.
|
||||||
|
|
||||||
|
To register, enable and start the service use the following commands:
|
||||||
|
|
||||||
|
- Reload the systemd manager configuration to make it aware of the new service file:
|
||||||
|
```shell
|
||||||
|
systemctl daemon-reload
|
||||||
|
```
|
||||||
|
- Start the service:
|
||||||
|
```shell
|
||||||
|
systemctl start darkflame.service
|
||||||
|
```
|
||||||
|
- Enable OR disable the service to start on boot using:
|
||||||
|
```shell
|
||||||
|
systemctl enable darkflame.service
|
||||||
|
systemctl disable darkflame.service
|
||||||
|
```
|
||||||
|
- Verify that the service is running without errors:
|
||||||
|
```shell
|
||||||
|
systemctl status darkflame.service
|
||||||
|
```
|
||||||
|
- You can also restart, stop, or check the logs of the service using journalctl
|
||||||
|
```shell
|
||||||
|
systemctl restart darkflame.service
|
||||||
|
systemctl stop darkflame.service
|
||||||
|
journalctl -xeu darkflame.service
|
||||||
|
```
|
||||||
|
|
||||||
### First admin user
|
### First admin user
|
||||||
Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
Run `MasterServer -a` to get prompted to create an admin account. This method is only intended for the system administrator as a means to get started, do NOT use this method to create accounts for other users!
|
||||||
|
|
||||||
@@ -285,6 +326,7 @@ Below are known good SHA256 checksums of the client:
|
|||||||
* `0d862f71eedcadc4494c4358261669721b40b2131101cbd6ef476c5a6ec6775b` (unpacked client, includes extra locales, rar compressed)
|
* `0d862f71eedcadc4494c4358261669721b40b2131101cbd6ef476c5a6ec6775b` (unpacked client, includes extra locales, rar compressed)
|
||||||
|
|
||||||
If the returned hash matches one of the lines above then you can continue with setting up the server. If you are using a fully downloaded and complete client from live, then it will work, but the hash above may not match. Otherwise you must obtain a full install of LEGO® Universe 1.10.64.
|
If the returned hash matches one of the lines above then you can continue with setting up the server. If you are using a fully downloaded and complete client from live, then it will work, but the hash above may not match. Otherwise you must obtain a full install of LEGO® Universe 1.10.64.
|
||||||
|
You must also make absolutely sure your LEGO Universe client is not in a Windows OneDrive. DLU is not and will not support a client being stored in a OneDrive, so ensure you have moved the client outside of that location.
|
||||||
|
|
||||||
### Darkflame Universe Client
|
### Darkflame Universe Client
|
||||||
Darkflame Universe clients identify themselves using a higher version number than the regular live clients out there.
|
Darkflame Universe clients identify themselves using a higher version number than the regular live clients out there.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
//DLU Includes:
|
//DLU Includes:
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Diagnostics.h"
|
#include "Diagnostics.h"
|
||||||
@@ -25,14 +25,14 @@
|
|||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
namespace Game {
|
namespace Game {
|
||||||
dLogger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger();
|
Logger* SetupLogger();
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@@ -51,20 +51,14 @@ int main(int argc, char** argv) {
|
|||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||||
|
|
||||||
Game::logger->Log("AuthServer", "Starting Auth server...");
|
LOG("Starting Auth server...");
|
||||||
Game::logger->Log("AuthServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||||
Game::logger->Log("AuthServer", "Compiled on: %s", __TIMESTAMP__);
|
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||||
|
|
||||||
//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");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
Database::Connect();
|
||||||
} catch (sql::SQLException& ex) {
|
} catch (sql::SQLException& ex) {
|
||||||
Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s", ex.what());
|
LOG("Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("AuthServer");
|
Database::Destroy("AuthServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
@@ -74,15 +68,12 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort = 1500;
|
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;
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
delete stmt;
|
if (masterInfo) {
|
||||||
|
masterIP = masterInfo->ip;
|
||||||
|
masterPort = masterInfo->port;
|
||||||
|
}
|
||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
@@ -103,6 +94,8 @@ int main(int argc, char** argv) {
|
|||||||
uint32_t framesSinceMasterDisconnect = 0;
|
uint32_t framesSinceMasterDisconnect = 0;
|
||||||
uint32_t framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
|
||||||
|
AuthPackets::LoadClaimCodes();
|
||||||
|
|
||||||
while (!Game::shouldShutdown) {
|
while (!Game::shouldShutdown) {
|
||||||
//Check if we're still connected to master:
|
//Check if we're still connected to master:
|
||||||
if (!Game::server->GetIsConnectedToMaster()) {
|
if (!Game::server->GetIsConnectedToMaster()) {
|
||||||
@@ -134,16 +127,12 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort;
|
uint32_t masterPort;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
auto res = stmt->executeQuery();
|
if (masterInfo) {
|
||||||
while (res->next()) {
|
masterIP = masterInfo->ip;
|
||||||
masterIP = res->getString(1).c_str();
|
masterPort = masterInfo->port;
|
||||||
masterPort = res->getInt(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete res;
|
|
||||||
delete stmt;
|
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
|
|
||||||
@@ -161,7 +150,7 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger() {
|
Logger* SetupLogger() {
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/AuthServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/AuthServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
||||||
bool logToConsole = false;
|
bool logToConsole = false;
|
||||||
bool logDebugStatements = false;
|
bool logDebugStatements = false;
|
||||||
@@ -170,7 +159,7 @@ dLogger* SetupLogger() {
|
|||||||
logDebugStatements = true;
|
logDebugStatements = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return new dLogger(logPath, logToConsole, logDebugStatements);
|
return new Logger(logPath, logToConsole, logDebugStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
@@ -32,15 +32,11 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Read player names that are ok as well:
|
//Read player names that are ok as well:
|
||||||
auto stmt = Database::CreatePreppedStmt("select name from charinfo;");
|
auto approvedNames = Database::Get()->GetApprovedCharacterNames();
|
||||||
auto res = stmt->executeQuery();
|
for (auto& name : approvedNames) {
|
||||||
while (res->next()) {
|
std::transform(name.begin(), name.end(), name.begin(), ::tolower); //Transform to lowercase
|
||||||
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() {
|
||||||
@@ -144,7 +140,7 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
|
|||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
position += segment.length() + 1;
|
position += originalSegment.length() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return listOfBadSegments;
|
return listOfBadSegments;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
set(DCHATSERVER_SOURCES
|
set(DCHATSERVER_SOURCES
|
||||||
|
"ChatIgnoreList.cpp"
|
||||||
"ChatPacketHandler.cpp"
|
"ChatPacketHandler.cpp"
|
||||||
"PlayerContainer.cpp"
|
"PlayerContainer.cpp"
|
||||||
)
|
)
|
||||||
|
|||||||
173
dChatServer/ChatIgnoreList.cpp
Normal file
173
dChatServer/ChatIgnoreList.cpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
#include "ChatIgnoreList.h"
|
||||||
|
#include "PlayerContainer.h"
|
||||||
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "PacketUtils.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "eObjectBits.h"
|
||||||
|
|
||||||
|
#include "Database.h"
|
||||||
|
|
||||||
|
// A note to future readers, The client handles all the actual ignoring logic:
|
||||||
|
// not allowing teams, rejecting DMs, friends requets etc.
|
||||||
|
// The only thing not auto-handled is instance activities force joining the team on the server.
|
||||||
|
|
||||||
|
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
|
bitStream.Write(receivingPlayer);
|
||||||
|
|
||||||
|
//portion that will get routed:
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiver->ignoredPlayers.empty()) {
|
||||||
|
LOG_DEBUG("Player %llu already has an ignore list", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
|
||||||
|
if (ignoreList.empty()) {
|
||||||
|
LOG_DEBUG("Player %llu has no ignores", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& ignoredPlayer : ignoreList) {
|
||||||
|
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayer.id, ignoredPlayer.name });
|
||||||
|
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::GET_IGNORE);
|
||||||
|
|
||||||
|
bitStream.Write<uint8_t>(false); // Probably is Is Free Trial, but we don't care about that
|
||||||
|
bitStream.Write<uint16_t>(0); // literally spacing due to struct alignment
|
||||||
|
|
||||||
|
bitStream.Write<uint16_t>(receiver->ignoredPlayers.size());
|
||||||
|
for (const auto& ignoredPlayer : receiver->ignoredPlayers) {
|
||||||
|
bitStream.Write(ignoredPlayer.playerId);
|
||||||
|
bitStream.Write(LUWString(ignoredPlayer.playerName, 36));
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::AddIgnore(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int32_t MAX_IGNORES = 32;
|
||||||
|
if (receiver->ignoredPlayers.size() > MAX_IGNORES) {
|
||||||
|
LOG_DEBUG("Player %llu has too many ignores", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
|
||||||
|
|
||||||
|
LUWString toIgnoreName(33);
|
||||||
|
inStream.Read(toIgnoreName);
|
||||||
|
std::string toIgnoreStr = toIgnoreName.GetAsString();
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::ADD_IGNORE);
|
||||||
|
|
||||||
|
// Check if the player exists
|
||||||
|
LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY;
|
||||||
|
if (toIgnoreStr == receiver->playerName || toIgnoreStr.find("[GM]") == 0) {
|
||||||
|
LOG_DEBUG("Player %llu tried to ignore themselves", playerId);
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR);
|
||||||
|
} else if (std::count(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), toIgnoreStr) > 0) {
|
||||||
|
LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED);
|
||||||
|
} else {
|
||||||
|
// Get the playerId falling back to query if not online
|
||||||
|
auto* playerData = Game::playerContainer.GetPlayerData(toIgnoreStr);
|
||||||
|
if (!playerData) {
|
||||||
|
// Fall back to query
|
||||||
|
auto player = Database::Get()->GetCharacterInfo(toIgnoreStr);
|
||||||
|
if (!player || player->name != toIgnoreStr) {
|
||||||
|
LOG_DEBUG("Player %s not found", toIgnoreStr.c_str());
|
||||||
|
} else {
|
||||||
|
ignoredPlayerId = player->id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ignoredPlayerId = playerData->playerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
||||||
|
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
|
||||||
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
|
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayerId, toIgnoreStr });
|
||||||
|
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
|
||||||
|
} else {
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::PLAYER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LUWString playerNameSend(toIgnoreStr, 33);
|
||||||
|
bitStream.Write(playerNameSend);
|
||||||
|
bitStream.Write(ignoredPlayerId);
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::RemoveIgnore(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
|
||||||
|
|
||||||
|
LUWString removedIgnoreName(33);
|
||||||
|
inStream.Read(removedIgnoreName);
|
||||||
|
std::string removedIgnoreStr = removedIgnoreName.GetAsString();
|
||||||
|
|
||||||
|
auto toRemove = std::remove(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), removedIgnoreStr);
|
||||||
|
if (toRemove == receiver->ignoredPlayers.end()) {
|
||||||
|
LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
|
||||||
|
receiver->ignoredPlayers.erase(toRemove, receiver->ignoredPlayers.end());
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::REMOVE_IGNORE);
|
||||||
|
|
||||||
|
bitStream.Write<int8_t>(0);
|
||||||
|
LUWString playerNameSend(removedIgnoreStr, 33);
|
||||||
|
bitStream.Write(playerNameSend);
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
||||||
27
dChatServer/ChatIgnoreList.h
Normal file
27
dChatServer/ChatIgnoreList.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __CHATIGNORELIST__H__
|
||||||
|
#define __CHATIGNORELIST__H__
|
||||||
|
|
||||||
|
struct Packet;
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ChatIgnoreList {
|
||||||
|
void GetIgnoreList(Packet* packet);
|
||||||
|
void AddIgnore(Packet* packet);
|
||||||
|
void RemoveIgnore(Packet* packet);
|
||||||
|
|
||||||
|
enum class Response : uint8_t {
|
||||||
|
ADD_IGNORE = 32,
|
||||||
|
REMOVE_IGNORE = 33,
|
||||||
|
GET_IGNORE = 34,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AddResponse : uint8_t {
|
||||||
|
SUCCESS,
|
||||||
|
ALREADY_IGNORED,
|
||||||
|
PLAYER_NOT_FOUND,
|
||||||
|
GENERAL_ERROR,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__CHATIGNORELIST__H__
|
||||||
@@ -3,10 +3,11 @@
|
|||||||
#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"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "eAddFriendResponseCode.h"
|
#include "eAddFriendResponseCode.h"
|
||||||
#include "eAddFriendResponseType.h"
|
#include "eAddFriendResponseType.h"
|
||||||
#include "RakString.h"
|
#include "RakString.h"
|
||||||
@@ -18,46 +19,29 @@
|
|||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
#include "eGameMessageType.h"
|
#include "eGameMessageType.h"
|
||||||
|
|
||||||
extern PlayerContainer playerContainer;
|
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||||
//Get from the packet which player we want to do something with:
|
//Get from the packet which player we want to do something with:
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = 0;
|
LWOOBJID playerID = 0;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto player = playerContainer.GetPlayerData(playerID);
|
auto player = Game::playerContainer.GetPlayerData(playerID);
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
//Get our friends list from the Db. Using a derived table since the friend of a player can be in either column.
|
auto friendsList = Database::Get()->GetFriendsList(playerID);
|
||||||
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt(
|
for (const auto& friendData : friendsList) {
|
||||||
"SELECT fr.requested_player, best_friend, ci.name FROM "
|
|
||||||
"(SELECT CASE "
|
|
||||||
"WHEN player_id = ? THEN friend_id "
|
|
||||||
"WHEN friend_id = ? THEN player_id "
|
|
||||||
"END AS requested_player, best_friend FROM friends) AS fr "
|
|
||||||
"JOIN charinfo AS ci ON ci.id = fr.requested_player "
|
|
||||||
"WHERE fr.requested_player IS NOT NULL AND fr.requested_player != ?;"));
|
|
||||||
stmt->setUInt(1, static_cast<uint32_t>(playerID));
|
|
||||||
stmt->setUInt(2, static_cast<uint32_t>(playerID));
|
|
||||||
stmt->setUInt(3, static_cast<uint32_t>(playerID));
|
|
||||||
|
|
||||||
std::vector<FriendData> friends;
|
|
||||||
|
|
||||||
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery());
|
|
||||||
while (res->next()) {
|
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
fd.isFTP = false; // not a thing in DLU
|
fd.isFTP = false; // not a thing in DLU
|
||||||
fd.friendID = res->getUInt(1);
|
fd.friendID = friendData.friendID;
|
||||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::PERSISTENT);
|
GeneralUtils::SetBit(fd.friendID, eObjectBits::PERSISTENT);
|
||||||
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
fd.isBestFriend = res->getInt(2) == 3; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
|
||||||
if (fd.isBestFriend) player->countOfBestFriends += 1;
|
if (fd.isBestFriend) player->countOfBestFriends += 1;
|
||||||
fd.friendName = res->getString(3);
|
fd.friendName = friendData.friendName;
|
||||||
|
|
||||||
//Now check if they're online:
|
//Now check if they're online:
|
||||||
auto fr = playerContainer.GetPlayerData(fd.friendID);
|
auto fr = Game::playerContainer.GetPlayerData(fd.friendID);
|
||||||
|
|
||||||
if (fr) {
|
if (fr) {
|
||||||
fd.isOnline = true;
|
fd.isOnline = true;
|
||||||
@@ -70,34 +54,29 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
fd.zoneID = LWOZONEID();
|
fd.zoneID = LWOZONEID();
|
||||||
}
|
}
|
||||||
|
|
||||||
friends.push_back(fd);
|
player->friends.push_back(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
//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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
|
BitStreamUtils::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)player->friends.size());
|
||||||
|
|
||||||
for (auto& data : friends) {
|
for (auto& data : player->friends) {
|
||||||
data.Serialize(bitStream);
|
data.Serialize(bitStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
player->friends = friends;
|
|
||||||
|
|
||||||
SystemAddress sysAddr = player->sysAddr;
|
SystemAddress sysAddr = player->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||||
auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends");
|
|
||||||
// If this config option doesn't exist, default to 5 which is what live used.
|
|
||||||
auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U;
|
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID requestorPlayerID;
|
LWOOBJID requestorPlayerID;
|
||||||
inStream.Read(requestorPlayerID);
|
inStream.Read(requestorPlayerID);
|
||||||
@@ -116,12 +95,17 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
char isBestFriendRequest{};
|
char isBestFriendRequest{};
|
||||||
inStream.Read(isBestFriendRequest);
|
inStream.Read(isBestFriendRequest);
|
||||||
|
|
||||||
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
|
auto requestor = Game::playerContainer.GetPlayerData(requestorPlayerID);
|
||||||
|
if (!requestor) {
|
||||||
|
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (requestor->playerName == playerName) {
|
if (requestor->playerName == playerName) {
|
||||||
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
|
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
|
std::unique_ptr<PlayerData> requestee(Game::playerContainer.GetPlayerData(playerName));
|
||||||
|
|
||||||
// Check if player is online first
|
// Check if player is online first
|
||||||
if (isBestFriendRequest && !requestee) {
|
if (isBestFriendRequest && !requestee) {
|
||||||
@@ -149,35 +133,26 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
// If at this point we dont have a target, then they arent online and we cant send the request.
|
// If at this point we dont have a target, then they arent online and we cant send the request.
|
||||||
// Send the response code that corresponds to what the error is.
|
// Send the response code that corresponds to what the error is.
|
||||||
if (!requestee) {
|
if (!requestee) {
|
||||||
std::unique_ptr<sql::PreparedStatement> nameQuery(Database::CreatePreppedStmt("SELECT name from charinfo where name = ?;"));
|
|
||||||
nameQuery->setString(1, playerName);
|
|
||||||
std::unique_ptr<sql::ResultSet> result(nameQuery->executeQuery());
|
|
||||||
|
|
||||||
requestee.reset(new PlayerData());
|
requestee.reset(new PlayerData());
|
||||||
requestee->playerName = playerName;
|
requestee->playerName = playerName;
|
||||||
|
auto responseType = Database::Get()->GetCharacterInfo(playerName)
|
||||||
|
? eAddFriendResponseType::NOTONLINE
|
||||||
|
: eAddFriendResponseType::INVALIDCHARACTER;
|
||||||
|
|
||||||
SendFriendResponse(requestor, requestee.get(), result->next() ? eAddFriendResponseType::NOTONLINE : eAddFriendResponseType::INVALIDCHARACTER);
|
SendFriendResponse(requestor, requestee.get(), responseType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBestFriendRequest) {
|
if (isBestFriendRequest) {
|
||||||
std::unique_ptr<sql::PreparedStatement> friendUpdate(Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
|
||||||
friendUpdate->setUInt(1, static_cast<uint32_t>(requestorPlayerID));
|
|
||||||
friendUpdate->setUInt(2, static_cast<uint32_t>(requestee->playerID));
|
|
||||||
friendUpdate->setUInt(3, static_cast<uint32_t>(requestee->playerID));
|
|
||||||
friendUpdate->setUInt(4, static_cast<uint32_t>(requestorPlayerID));
|
|
||||||
std::unique_ptr<sql::ResultSet> result(friendUpdate->executeQuery());
|
|
||||||
|
|
||||||
LWOOBJID queryPlayerID = LWOOBJID_EMPTY;
|
|
||||||
LWOOBJID queryFriendID = LWOOBJID_EMPTY;
|
|
||||||
uint8_t oldBestFriendStatus{};
|
uint8_t oldBestFriendStatus{};
|
||||||
uint8_t bestFriendStatus{};
|
uint8_t bestFriendStatus{};
|
||||||
|
auto bestFriendInfo = Database::Get()->GetBestFriendStatus(requestorPlayerID, requestee->playerID);
|
||||||
if (result->next()) {
|
if (bestFriendInfo) {
|
||||||
// Get the IDs
|
// Get the IDs
|
||||||
queryPlayerID = result->getInt(1);
|
LWOOBJID queryPlayerID = bestFriendInfo->playerCharacterId;
|
||||||
queryFriendID = result->getInt(2);
|
LWOOBJID queryFriendID = bestFriendInfo->friendCharacterId;
|
||||||
oldBestFriendStatus = result->getInt(3);
|
oldBestFriendStatus = bestFriendInfo->bestFriendStatus;
|
||||||
bestFriendStatus = oldBestFriendStatus;
|
bestFriendStatus = oldBestFriendStatus;
|
||||||
|
|
||||||
// Set the bits
|
// Set the bits
|
||||||
@@ -198,22 +173,17 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
|
|
||||||
// Only do updates if there was a change in the bff status.
|
// Only do updates if there was a change in the bff status.
|
||||||
if (oldBestFriendStatus != bestFriendStatus) {
|
if (oldBestFriendStatus != bestFriendStatus) {
|
||||||
if (requestee->countOfBestFriends >= maxNumberOfBestFriends || requestor->countOfBestFriends >= maxNumberOfBestFriends) {
|
auto maxBestFriends = Game::playerContainer.GetMaxNumberOfBestFriends();
|
||||||
if (requestee->countOfBestFriends >= maxNumberOfBestFriends) {
|
if (requestee->countOfBestFriends >= maxBestFriends || requestor->countOfBestFriends >= maxBestFriends) {
|
||||||
|
if (requestee->countOfBestFriends >= maxBestFriends) {
|
||||||
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
||||||
}
|
}
|
||||||
if (requestor->countOfBestFriends >= maxNumberOfBestFriends) {
|
if (requestor->countOfBestFriends >= maxBestFriends) {
|
||||||
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::YOURFRIENDSLISTFULL, false);
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::YOURFRIENDSLISTFULL, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Then update the database with this new info.
|
// Then update the database with this new info.
|
||||||
std::unique_ptr<sql::PreparedStatement> updateQuery(Database::CreatePreppedStmt("UPDATE friends SET best_friend = ? WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee->playerID, bestFriendStatus);
|
||||||
updateQuery->setUInt(1, bestFriendStatus);
|
|
||||||
updateQuery->setUInt(2, static_cast<uint32_t>(requestorPlayerID));
|
|
||||||
updateQuery->setUInt(3, static_cast<uint32_t>(requestee->playerID));
|
|
||||||
updateQuery->setUInt(4, static_cast<uint32_t>(requestee->playerID));
|
|
||||||
updateQuery->setUInt(5, static_cast<uint32_t>(requestorPlayerID));
|
|
||||||
updateQuery->executeUpdate();
|
|
||||||
// Sent the best friend update here if the value is 3
|
// Sent the best friend update here if the value is 3
|
||||||
if (bestFriendStatus == 3U) {
|
if (bestFriendStatus == 3U) {
|
||||||
requestee->countOfBestFriends += 1;
|
requestee->countOfBestFriends += 1;
|
||||||
@@ -236,8 +206,15 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Do not send this if we are requesting to be a best friend.
|
auto maxFriends = Game::playerContainer.GetMaxNumberOfFriends();
|
||||||
SendFriendRequest(requestee.get(), requestor);
|
if (requestee->friends.size() >= maxFriends) {
|
||||||
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
||||||
|
} else if (requestor->friends.size() >= maxFriends) {
|
||||||
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::YOURFRIENDSLISTFULL, false);
|
||||||
|
} else {
|
||||||
|
// Do not send this if we are requesting to be a best friend.
|
||||||
|
SendFriendRequest(requestee.get(), requestor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the player is actually a player and not a ghost one defined above, release it from being deleted.
|
// If the player is actually a player and not a ghost one defined above, release it from being deleted.
|
||||||
@@ -253,8 +230,8 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
|||||||
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
||||||
|
|
||||||
//Now to try and find both of these:
|
//Now to try and find both of these:
|
||||||
auto requestor = playerContainer.GetPlayerData(playerID);
|
auto requestor = Game::playerContainer.GetPlayerData(playerID);
|
||||||
auto requestee = playerContainer.GetPlayerData(friendName);
|
auto requestee = Game::playerContainer.GetPlayerData(friendName);
|
||||||
if (!requestor || !requestee) return;
|
if (!requestor || !requestee) return;
|
||||||
|
|
||||||
eAddFriendResponseType serverResponseCode{};
|
eAddFriendResponseType serverResponseCode{};
|
||||||
@@ -308,11 +285,7 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
|||||||
requesteeData.isOnline = true;
|
requesteeData.isOnline = true;
|
||||||
requestor->friends.push_back(requesteeData);
|
requestor->friends.push_back(requesteeData);
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> statement(Database::CreatePreppedStmt("INSERT IGNORE INTO `friends` (`player_id`, `friend_id`, `best_friend`) VALUES (?,?,?);"));
|
Database::Get()->AddFriend(requestor->playerID, requestee->playerID);
|
||||||
statement->setUInt(1, static_cast<uint32_t>(requestor->playerID));
|
|
||||||
statement->setUInt(2, static_cast<uint32_t>(requestee->playerID));
|
|
||||||
statement->setInt(3, 0);
|
|
||||||
statement->execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverResponseCode != eAddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends);
|
if (serverResponseCode != eAddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends);
|
||||||
@@ -327,28 +300,20 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
|
|
||||||
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
||||||
//First, we need to find their ID:
|
//First, we need to find their ID:
|
||||||
std::unique_ptr<sql::PreparedStatement> stmt(Database::CreatePreppedStmt("SELECT id FROM charinfo WHERE name=? LIMIT 1;"));
|
|
||||||
stmt->setString(1, friendName.c_str());
|
|
||||||
|
|
||||||
LWOOBJID friendID = 0;
|
LWOOBJID friendID = 0;
|
||||||
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery());
|
auto friendIdResult = Database::Get()->GetCharacterInfo(friendName);
|
||||||
while (res->next()) {
|
if (friendIdResult) {
|
||||||
friendID = res->getUInt(1);
|
friendID = friendIdResult->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert friendID to LWOOBJID
|
// Convert friendID to LWOOBJID
|
||||||
GeneralUtils::SetBit(friendID, eObjectBits::PERSISTENT);
|
GeneralUtils::SetBit(friendID, eObjectBits::PERSISTENT);
|
||||||
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(friendID, eObjectBits::CHARACTER);
|
||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> deletestmt(Database::CreatePreppedStmt("DELETE FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?) LIMIT 1;"));
|
Database::Get()->RemoveFriend(playerID, friendID);
|
||||||
deletestmt->setUInt(1, static_cast<uint32_t>(playerID));
|
|
||||||
deletestmt->setUInt(2, static_cast<uint32_t>(friendID));
|
|
||||||
deletestmt->setUInt(3, static_cast<uint32_t>(friendID));
|
|
||||||
deletestmt->setUInt(4, static_cast<uint32_t>(playerID));
|
|
||||||
deletestmt->execute();
|
|
||||||
|
|
||||||
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
||||||
auto goonA = playerContainer.GetPlayerData(playerID);
|
auto goonA = Game::playerContainer.GetPlayerData(playerID);
|
||||||
if (goonA) {
|
if (goonA) {
|
||||||
// Remove the friend from our list of friends
|
// Remove the friend from our list of friends
|
||||||
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) {
|
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) {
|
||||||
@@ -361,7 +326,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
SendRemoveFriend(goonA, friendName, true);
|
SendRemoveFriend(goonA, friendName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto goonB = playerContainer.GetPlayerData(friendID);
|
auto goonB = Game::playerContainer.GetPlayerData(friendID);
|
||||||
if (!goonB) return;
|
if (!goonB) return;
|
||||||
// Do it again for other person
|
// Do it again for other person
|
||||||
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) {
|
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) {
|
||||||
@@ -372,7 +337,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string goonAName = GeneralUtils::UTF16ToWTF8(playerContainer.GetName(playerID));
|
std::string goonAName = GeneralUtils::UTF16ToWTF8(Game::playerContainer.GetName(playerID));
|
||||||
SendRemoveFriend(goonB, goonAName, true);
|
SendRemoveFriend(goonB, goonAName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,11 +346,11 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto* sender = playerContainer.GetPlayerData(playerID);
|
auto* sender = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (sender == nullptr) return;
|
if (sender == nullptr) return;
|
||||||
|
|
||||||
if (playerContainer.GetIsMuted(sender)) return;
|
if (Game::playerContainer.GetIsMuted(sender)) return;
|
||||||
|
|
||||||
const auto senderName = std::string(sender->playerName.c_str());
|
const auto senderName = std::string(sender->playerName.c_str());
|
||||||
|
|
||||||
@@ -396,37 +361,37 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
|
std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
|
LOG("Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
|
||||||
|
|
||||||
if (channel != 8) return;
|
if (channel != 8) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team == nullptr) return;
|
if (team == nullptr) return;
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs) {
|
for (const auto memberId : team->memberIDs) {
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) return;
|
if (otherMember == nullptr) return;
|
||||||
|
|
||||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(otherMember->playerID);
|
bitStream.Write(otherMember->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::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);
|
||||||
PacketUtils::WritePacketWString(senderName, 33, &bitStream);
|
bitStream.Write(LUWString(senderName));
|
||||||
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
|
||||||
PacketUtils::WritePacketWString(otherName, 33, &bitStream);
|
bitStream.Write(LUWString(otherName));
|
||||||
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?
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = otherMember->sysAddr;
|
SystemAddress sysAddr = otherMember->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -434,16 +399,16 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||||
LWOOBJID senderID = PacketUtils::ReadPacketS64(0x08, packet);
|
LWOOBJID senderID = PacketUtils::ReadS64(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);
|
||||||
|
|
||||||
//Get the bois:
|
//Get the bois:
|
||||||
auto goonA = playerContainer.GetPlayerData(senderID);
|
auto goonA = Game::playerContainer.GetPlayerData(senderID);
|
||||||
auto goonB = playerContainer.GetPlayerData(receiverName);
|
auto goonB = Game::playerContainer.GetPlayerData(receiverName);
|
||||||
if (!goonA || !goonB) return;
|
if (!goonA || !goonB) return;
|
||||||
|
|
||||||
if (playerContainer.GetIsMuted(goonA)) return;
|
if (Game::playerContainer.GetIsMuted(goonA)) return;
|
||||||
|
|
||||||
std::string goonAName = goonA->playerName.c_str();
|
std::string goonAName = goonA->playerName.c_str();
|
||||||
std::string goonBName = goonB->playerName.c_str();
|
std::string goonBName = goonB->playerName.c_str();
|
||||||
@@ -451,21 +416,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the sender:
|
//To the sender:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonA->playerID);
|
bitStream.Write(goonA->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::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);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
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
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
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
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonA->sysAddr;
|
SystemAddress sysAddr = goonA->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -474,21 +439,21 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
//To the receiver:
|
//To the receiver:
|
||||||
{
|
{
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
bitStream.Write(goonB->playerID);
|
bitStream.Write(goonB->playerID);
|
||||||
|
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::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);
|
||||||
PacketUtils::WritePacketWString(goonAName, 33, &bitStream);
|
bitStream.Write(LUWString(goonAName));
|
||||||
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
|
||||||
PacketUtils::WritePacketWString(goonBName, 33, &bitStream);
|
bitStream.Write(LUWString(goonBName));
|
||||||
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
|
||||||
PacketUtils::WritePacketWString(message, 512, &bitStream);
|
bitStream.Write(LUWString(message, 512));
|
||||||
|
|
||||||
SystemAddress sysAddr = goonB->sysAddr;
|
SystemAddress sysAddr = goonB->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@@ -501,38 +466,38 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
|||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
auto* player = playerContainer.GetPlayerData(playerID);
|
auto* player = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
team = playerContainer.CreateTeam(playerID);
|
team = Game::playerContainer.CreateTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* other = playerContainer.GetPlayerData(invitedPlayer);
|
auto* other = Game::playerContainer.GetPlayerData(invitedPlayer);
|
||||||
|
|
||||||
if (other == nullptr) {
|
if (other == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerContainer.GetTeam(other->playerID) != nullptr) {
|
if (Game::playerContainer.GetTeam(other->playerID) != nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team->memberIDs.size() > 3) {
|
if (team->memberIDs.size() > 3) {
|
||||||
// no more teams greater than 4
|
// no more teams greater than 4
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Someone tried to invite a 5th player to a team");
|
LOG("Someone tried to invite a 5th player to a team");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SendTeamInvite(other, player);
|
SendTeamInvite(other, player);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
|
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
||||||
@@ -546,26 +511,26 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
|||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(leaderID);
|
inStream.Read(leaderID);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
|
LOG("Accepted invite: %llu -> %llu (%d)", playerID, leaderID, declined);
|
||||||
|
|
||||||
if (declined) {
|
if (declined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(leaderID);
|
auto* team = Game::playerContainer.GetTeam(leaderID);
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
Game::logger->Log("ChatPacketHandler", "Failed to find team for leader (%llu)", leaderID);
|
LOG("Failed to find team for leader (%llu)", leaderID);
|
||||||
|
|
||||||
team = playerContainer.GetTeam(playerID);
|
team = Game::playerContainer.GetTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
Game::logger->Log("ChatPacketHandler", "Failed to find team for player (%llu)", playerID);
|
LOG("Failed to find team for player (%llu)", playerID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.AddMember(team, playerID);
|
Game::playerContainer.AddMember(team, playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
||||||
@@ -575,12 +540,12 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
|||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) leaving team", playerID);
|
LOG("(%llu) leaving team", playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true);
|
Game::playerContainer.RemoveMember(team, playerID, false, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,26 +556,26 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
|||||||
|
|
||||||
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
||||||
|
|
||||||
auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
|
auto* kicked = Game::playerContainer.GetPlayerData(kickedPlayer);
|
||||||
|
|
||||||
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
if (kicked != nullptr) {
|
if (kicked != nullptr) {
|
||||||
kickedId = kicked->playerID;
|
kickedId = kicked->playerID;
|
||||||
} else {
|
} else {
|
||||||
kickedId = playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kickedId == LWOOBJID_EMPTY) return;
|
if (kickedId == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
||||||
|
|
||||||
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
Game::playerContainer.RemoveMember(team, kickedId, false, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,18 +586,18 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
|||||||
|
|
||||||
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
Game::logger->Log("ChatPacketHandler", "(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
||||||
|
|
||||||
auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
|
auto* promoted = Game::playerContainer.GetPlayerData(promotedPlayer);
|
||||||
|
|
||||||
if (promoted == nullptr) return;
|
if (promoted == nullptr) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
playerContainer.PromoteMember(team, promoted->playerID);
|
Game::playerContainer.PromoteMember(team, promoted->playerID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,16 +611,16 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
|||||||
char option;
|
char option;
|
||||||
inStream.Read(option);
|
inStream.Read(option);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
team->lootFlag = option;
|
team->lootFlag = option;
|
||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
Game::playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
playerContainer.UpdateTeamsOnWorld(team, false);
|
Game::playerContainer.UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,18 +629,18 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
auto* data = playerContainer.GetPlayerData(playerID);
|
auto* data = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (team != nullptr && data != nullptr) {
|
if (team != nullptr && data != nullptr) {
|
||||||
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
|
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
Game::playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team->memberIDs.size() <= 1 && !team->local) {
|
if (team->memberIDs.size() <= 1 && !team->local) {
|
||||||
playerContainer.DisbandTeam(team);
|
Game::playerContainer.DisbandTeam(team);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -686,16 +651,16 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
Game::playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs) {
|
for (const auto memberId : team->memberIDs) {
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (memberId == playerID) continue;
|
if (memberId == playerID) continue;
|
||||||
|
|
||||||
const auto memberName = playerContainer.GetName(memberId);
|
const auto memberName = Game::playerContainer.GetName(memberId);
|
||||||
|
|
||||||
if (otherMember != nullptr) {
|
if (otherMember != nullptr) {
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
||||||
@@ -703,19 +668,19 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.UpdateTeamsOnWorld(team, false);
|
Game::playerContainer.UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
bitStream.Write(sender->playerID);
|
bitStream.Write(sender->playerID);
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
@@ -724,7 +689,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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -751,7 +716,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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -776,7 +741,7 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -793,7 +758,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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -822,7 +787,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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -848,7 +813,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;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
@@ -882,16 +847,16 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
|
BitStreamUtils::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();
|
||||||
|
|
||||||
PacketUtils::WritePacketWString(playerName, 33, &bitStream);
|
bitStream.Write(LUWString(playerName));
|
||||||
|
|
||||||
bitStream.Write(playerData->zoneID.GetMapID());
|
bitStream.Write(playerData->zoneID.GetMapID());
|
||||||
bitStream.Write(playerData->zoneID.GetInstanceID());
|
bitStream.Write(playerData->zoneID.GetInstanceID());
|
||||||
@@ -921,12 +886,12 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
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;
|
||||||
@@ -937,16 +902,16 @@ void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sen
|
|||||||
if (!receiver || !sender) return;
|
if (!receiver || !sender) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
|
BitStreamUtils::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
|
||||||
PacketUtils::WritePacketWString(sender->playerName.c_str(), 33, &bitStream);
|
bitStream.Write(LUWString(sender->playerName.c_str()));
|
||||||
// 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);
|
||||||
@@ -962,13 +927,13 @@ void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& pers
|
|||||||
if (!receiver) return;
|
if (!receiver) return;
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::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:
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
|
||||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||||
PacketUtils::WritePacketWString(personToRemove, 33, &bitStream);
|
bitStream.Write(LUWString(personToRemove));
|
||||||
|
|
||||||
SystemAddress sysAddr = receiver->sysAddr;
|
SystemAddress sysAddr = receiver->sysAddr;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//DLU Includes:
|
//DLU Includes:
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "dChatFilter.h"
|
#include "dChatFilter.h"
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "eChatMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
#include "eWorldMessageType.h"
|
#include "eWorldMessageType.h"
|
||||||
|
#include "ChatIgnoreList.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
@@ -27,21 +28,19 @@
|
|||||||
#include <MessageIdentifiers.h>
|
#include <MessageIdentifiers.h>
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
dLogger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
dChatFilter* chatFilter = nullptr;
|
dChatFilter* chatFilter = nullptr;
|
||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
|
PlayerContainer playerContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger* SetupLogger();
|
||||||
dLogger* SetupLogger();
|
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
PlayerContainer playerContainer;
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
constexpr uint32_t chatFramerate = mediumFramerate;
|
constexpr uint32_t chatFramerate = mediumFramerate;
|
||||||
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
|
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
|
||||||
@@ -58,9 +57,9 @@ int main(int argc, char** argv) {
|
|||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||||
|
|
||||||
Game::logger->Log("ChatServer", "Starting Chat server...");
|
LOG("Starting Chat server...");
|
||||||
Game::logger->Log("ChatServer", "Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
LOG("Version: %i.%i", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR);
|
||||||
Game::logger->Log("ChatServer", "Compiled on: %s", __TIMESTAMP__);
|
LOG("Compiled on: %s", __TIMESTAMP__);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string clientPathStr = Game::config->GetValue("client_location");
|
std::string clientPathStr = Game::config->GetValue("client_location");
|
||||||
@@ -72,21 +71,16 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Game::assetManager = new AssetManager(clientPath);
|
Game::assetManager = new AssetManager(clientPath);
|
||||||
} catch (std::runtime_error& ex) {
|
} catch (std::runtime_error& ex) {
|
||||||
Game::logger->Log("ChatServer", "Got an error while setting up assets: %s", ex.what());
|
LOG("Got an error while setting up assets: %s", ex.what());
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Connect to the MySQL Database
|
//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");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password);
|
Database::Connect();
|
||||||
} catch (sql::SQLException& ex) {
|
} catch (sql::SQLException& ex) {
|
||||||
Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s", ex.what());
|
LOG("Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
delete Game::server;
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
@@ -96,16 +90,11 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort = 1000;
|
uint32_t masterPort = 1000;
|
||||||
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT ip, port FROM servers WHERE name='master';");
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
auto res = stmt->executeQuery();
|
if (masterInfo) {
|
||||||
while (res->next()) {
|
masterIP = masterInfo->ip;
|
||||||
masterIP = res->getString(1).c_str();
|
masterPort = masterInfo->port;
|
||||||
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;
|
||||||
uint32_t ourPort = 1501;
|
uint32_t ourPort = 1501;
|
||||||
@@ -118,6 +107,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
|
Game::playerContainer.Initialize();
|
||||||
|
|
||||||
//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();
|
||||||
Packet* packet = nullptr;
|
Packet* packet = nullptr;
|
||||||
@@ -158,15 +149,12 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP for absolutely no reason:
|
//Find out the master's IP for absolutely no reason:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort;
|
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;
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
delete stmt;
|
if (masterInfo) {
|
||||||
|
masterIP = masterInfo->ip;
|
||||||
|
masterPort = masterInfo->port;
|
||||||
|
}
|
||||||
|
|
||||||
framesSinceLastSQLPing = 0;
|
framesSinceLastSQLPing = 0;
|
||||||
} else framesSinceLastSQLPing++;
|
} else framesSinceLastSQLPing++;
|
||||||
@@ -185,7 +173,7 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger() {
|
Logger* SetupLogger() {
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/ChatServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/ChatServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
||||||
bool logToConsole = false;
|
bool logToConsole = false;
|
||||||
bool logDebugStatements = false;
|
bool logDebugStatements = false;
|
||||||
@@ -194,16 +182,16 @@ dLogger* SetupLogger() {
|
|||||||
logDebugStatements = true;
|
logDebugStatements = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return new dLogger(logPath, logToConsole, logDebugStatements);
|
return new Logger(logPath, logToConsole, logDebugStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
Game::logger->Log("ChatServer", "A server has disconnected, erasing their connected players from the list.");
|
LOG("A server has disconnected, erasing their connected players from the list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||||
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
|
LOG("A server is connecting, awaiting user list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
|
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
|
||||||
@@ -211,19 +199,19 @@ void HandlePacket(Packet* packet) {
|
|||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
||||||
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
||||||
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
||||||
playerContainer.InsertPlayer(packet);
|
Game::playerContainer.InsertPlayer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
||||||
playerContainer.RemovePlayer(packet);
|
Game::playerContainer.RemovePlayer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::MUTE_UPDATE:
|
case eChatInternalMessageType::MUTE_UPDATE:
|
||||||
playerContainer.MuteUpdate(packet);
|
Game::playerContainer.MuteUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::CREATE_TEAM:
|
case eChatInternalMessageType::CREATE_TEAM:
|
||||||
playerContainer.CreateTeamServer(packet);
|
Game::playerContainer.CreateTeamServer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::ANNOUNCEMENT: {
|
case eChatInternalMessageType::ANNOUNCEMENT: {
|
||||||
@@ -234,7 +222,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
|
LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +233,15 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::GET_IGNORE_LIST:
|
case eChatMessageType::GET_IGNORE_LIST:
|
||||||
Game::logger->Log("ChatServer", "Asked for ignore list, but is unimplemented right now.");
|
ChatIgnoreList::GetIgnoreList(packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eChatMessageType::ADD_IGNORE:
|
||||||
|
ChatIgnoreList::AddIgnore(packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eChatMessageType::REMOVE_IGNORE:
|
||||||
|
ChatIgnoreList::RemoveIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_GET_STATUS:
|
case eChatMessageType::TEAM_GET_STATUS:
|
||||||
@@ -303,19 +299,19 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown CHAT id: %i", int(packet->data[3]));
|
LOG("Unknown CHAT id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
|
||||||
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
||||||
case eWorldMessageType::ROUTE_PACKET: {
|
case eWorldMessageType::ROUTE_PACKET: {
|
||||||
Game::logger->Log("ChatServer", "Routing packet from world");
|
LOG("Routing packet from world");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Game::logger->Log("ChatServer", "Unknown World id: %i", int(packet->data[3]));
|
LOG("Unknown World id: %i", int(packet->data[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,27 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "PacketUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "ChatPackets.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
PlayerContainer::PlayerContainer() {
|
void PlayerContainer::Initialize() {
|
||||||
|
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends"), m_MaxNumberOfBestFriends);
|
||||||
|
GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_friends"), m_MaxNumberOfFriends);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerContainer::~PlayerContainer() {
|
PlayerContainer::~PlayerContainer() {
|
||||||
mPlayers.clear();
|
m_Players.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TeamData::TeamData() {
|
||||||
|
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::InsertPlayer(Packet* packet) {
|
void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||||
@@ -35,19 +43,12 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
inStream.Read(data->muteExpire);
|
inStream.Read(data->muteExpire);
|
||||||
data->sysAddr = packet->systemAddress;
|
data->sysAddr = packet->systemAddress;
|
||||||
|
|
||||||
mNames[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName);
|
m_Names[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName);
|
||||||
|
|
||||||
mPlayers.insert(std::make_pair(data->playerID, data));
|
m_Players.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());
|
LOG("Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
|
||||||
|
|
||||||
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
Database::Get()->UpdateActivityLog(data->playerID, eActivityType::PlayerLoggedIn, data->zoneID.GetMapID());
|
||||||
|
|
||||||
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) {
|
||||||
@@ -81,17 +82,10 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::logger->Log("PlayerContainer", "Removed user: %llu", playerID);
|
LOG("Removed user: %llu", playerID);
|
||||||
mPlayers.erase(playerID);
|
m_Players.erase(playerID);
|
||||||
|
|
||||||
auto* insertLog = Database::CreatePreppedStmt("INSERT INTO activity_log (character_id, activity, time, map_id) VALUES (?, ?, ?, ?);");
|
Database::Get()->UpdateActivityLog(playerID, eActivityType::PlayerLoggedOut, player->zoneID.GetMapID());
|
||||||
|
|
||||||
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) {
|
||||||
@@ -104,7 +98,7 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
|
|||||||
auto* player = this->GetPlayerData(playerID);
|
auto* player = this->GetPlayerData(playerID);
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
Game::logger->Log("PlayerContainer", "Failed to find user: %llu", playerID);
|
LOG("Failed to find user: %llu", playerID);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -146,7 +140,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -185,7 +179,7 @@ TeamData* PlayerContainer::CreateLocalTeam(std::vector<LWOOBJID> members) {
|
|||||||
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
|
TeamData* PlayerContainer::CreateTeam(LWOOBJID leader, bool local) {
|
||||||
auto* team = new TeamData();
|
auto* team = new TeamData();
|
||||||
|
|
||||||
team->teamID = ++mTeamIDCounter;
|
team->teamID = ++m_TeamIDCounter;
|
||||||
team->leaderID = leader;
|
team->leaderID = leader;
|
||||||
team->local = local;
|
team->local = local;
|
||||||
|
|
||||||
@@ -207,6 +201,14 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||||
|
if (team->memberIDs.size() >= 4){
|
||||||
|
LOG("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;
|
||||||
@@ -345,7 +347,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
PacketUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
@@ -362,15 +364,15 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
|
std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
|
||||||
const auto& pair = mNames.find(playerID);
|
const auto& pair = m_Names.find(playerID);
|
||||||
|
|
||||||
if (pair == mNames.end()) return u"";
|
if (pair == m_Names.end()) return u"";
|
||||||
|
|
||||||
return pair->second;
|
return pair->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
||||||
for (const auto& pair : mNames) {
|
for (const auto& pair : m_Names) {
|
||||||
if (pair.second == playerName) {
|
if (pair.second == playerName) {
|
||||||
return pair.first;
|
return pair.first;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,32 @@
|
|||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct IgnoreData {
|
||||||
|
inline bool operator==(const std::string& other) const noexcept {
|
||||||
|
return playerName == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const LWOOBJID& other) const noexcept {
|
||||||
|
return playerId == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWOOBJID playerId;
|
||||||
|
std::string playerName;
|
||||||
|
};
|
||||||
|
|
||||||
struct PlayerData {
|
struct PlayerData {
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
std::string playerName;
|
std::string playerName;
|
||||||
SystemAddress sysAddr;
|
SystemAddress sysAddr;
|
||||||
LWOZONEID zoneID;
|
LWOZONEID zoneID;
|
||||||
std::vector<FriendData> friends;
|
std::vector<FriendData> friends;
|
||||||
|
std::vector<IgnoreData> ignoredPlayers;
|
||||||
time_t muteExpire;
|
time_t muteExpire;
|
||||||
uint8_t countOfBestFriends = 0;
|
uint8_t countOfBestFriends = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TeamData {
|
struct TeamData {
|
||||||
|
TeamData();
|
||||||
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
LWOOBJID teamID = LWOOBJID_EMPTY; // Internal use
|
||||||
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
LWOOBJID leaderID = LWOOBJID_EMPTY;
|
||||||
std::vector<LWOOBJID> memberIDs{};
|
std::vector<LWOOBJID> memberIDs{};
|
||||||
@@ -28,9 +43,9 @@ struct TeamData {
|
|||||||
|
|
||||||
class PlayerContainer {
|
class PlayerContainer {
|
||||||
public:
|
public:
|
||||||
PlayerContainer();
|
|
||||||
~PlayerContainer();
|
~PlayerContainer();
|
||||||
|
|
||||||
|
void Initialize();
|
||||||
void InsertPlayer(Packet* packet);
|
void InsertPlayer(Packet* packet);
|
||||||
void RemovePlayer(Packet* packet);
|
void RemovePlayer(Packet* packet);
|
||||||
void MuteUpdate(Packet* packet);
|
void MuteUpdate(Packet* packet);
|
||||||
@@ -38,13 +53,13 @@ public:
|
|||||||
void BroadcastMuteUpdate(LWOOBJID player, time_t time);
|
void BroadcastMuteUpdate(LWOOBJID player, time_t time);
|
||||||
|
|
||||||
PlayerData* GetPlayerData(const LWOOBJID& playerID) {
|
PlayerData* GetPlayerData(const LWOOBJID& playerID) {
|
||||||
auto it = mPlayers.find(playerID);
|
auto it = m_Players.find(playerID);
|
||||||
if (it != mPlayers.end()) return it->second;
|
if (it != m_Players.end()) return it->second;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerData* GetPlayerData(const std::string& playerName) {
|
PlayerData* GetPlayerData(const std::string& playerName) {
|
||||||
for (auto player : mPlayers) {
|
for (auto player : m_Players) {
|
||||||
if (player.second) {
|
if (player.second) {
|
||||||
std::string pn = player.second->playerName.c_str();
|
std::string pn = player.second->playerName.c_str();
|
||||||
if (pn == playerName) return player.second;
|
if (pn == playerName) return player.second;
|
||||||
@@ -66,13 +81,17 @@ public:
|
|||||||
std::u16string GetName(LWOOBJID playerID);
|
std::u16string GetName(LWOOBJID playerID);
|
||||||
LWOOBJID GetId(const std::u16string& playerName);
|
LWOOBJID GetId(const std::u16string& playerName);
|
||||||
bool GetIsMuted(PlayerData* data);
|
bool GetIsMuted(PlayerData* data);
|
||||||
|
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
|
||||||
|
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
|
||||||
|
|
||||||
std::map<LWOOBJID, PlayerData*>& GetAllPlayerData() { return mPlayers; }
|
std::map<LWOOBJID, PlayerData*>& GetAllPlayerData() { return m_Players; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LWOOBJID mTeamIDCounter = 0;
|
LWOOBJID m_TeamIDCounter = 0;
|
||||||
std::map<LWOOBJID, PlayerData*> mPlayers;
|
std::map<LWOOBJID, PlayerData*> m_Players;
|
||||||
std::vector<TeamData*> mTeams;
|
std::vector<TeamData*> mTeams;
|
||||||
std::unordered_map<LWOOBJID, std::u16string> mNames;
|
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
||||||
|
uint32_t m_MaxNumberOfBestFriends = 5;
|
||||||
|
uint32_t m_MaxNumberOfFriends = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define __AMF3__H__
|
#define __AMF3__H__
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "AmfSerialize.h"
|
#include "AmfSerialize.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
// Writes an AMFValue pointer to a RakNet::BitStream
|
// Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
template<>
|
template<>
|
||||||
@@ -29,7 +29,7 @@ void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
Game::logger->Log("AmfSerialize", "Encountered unwritable AMFType %i!", type);
|
LOG("Encountered unwritable AMFType %i!", type);
|
||||||
}
|
}
|
||||||
case eAmf::Undefined:
|
case eAmf::Undefined:
|
||||||
case eAmf::Null:
|
case eAmf::Null:
|
||||||
|
|||||||
@@ -9,13 +9,12 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
//! Forward declarations
|
//! Forward declarations
|
||||||
|
|
||||||
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase();
|
|
||||||
void WriteSd0Magic(char* input, uint32_t chunkSize);
|
void WriteSd0Magic(char* input, uint32_t chunkSize);
|
||||||
bool CheckSd0Magic(sql::Blob* streamToCheck);
|
bool CheckSd0Magic(std::istream& streamToCheck);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Truncates all models with broken data from the database.
|
* @brief Truncates all models with broken data from the database.
|
||||||
@@ -24,28 +23,24 @@ bool CheckSd0Magic(sql::Blob* streamToCheck);
|
|||||||
*/
|
*/
|
||||||
uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
||||||
uint32_t modelsTruncated{};
|
uint32_t modelsTruncated{};
|
||||||
auto modelsToTruncate = GetModelsFromDatabase();
|
auto modelsToTruncate = Database::Get()->GetAllUgcModels();
|
||||||
bool previousCommitValue = Database::GetAutoCommit();
|
bool previousCommitValue = Database::Get()->GetAutoCommit();
|
||||||
Database::SetAutoCommit(false);
|
Database::Get()->SetAutoCommit(false);
|
||||||
while (modelsToTruncate->next()) {
|
for (auto& model : modelsToTruncate) {
|
||||||
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::string completeUncompressedModel{};
|
std::string completeUncompressedModel{};
|
||||||
uint32_t chunkCount{};
|
uint32_t chunkCount{};
|
||||||
uint64_t modelId = modelsToTruncate->getInt(1);
|
|
||||||
std::unique_ptr<sql::Blob> modelAsSd0(modelsToTruncate->getBlob(2));
|
|
||||||
// Check that header is sd0 by checking for the sd0 magic.
|
// Check that header is sd0 by checking for the sd0 magic.
|
||||||
if (CheckSd0Magic(modelAsSd0.get())) {
|
if (CheckSd0Magic(model.lxfmlData)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t chunkSize{};
|
uint32_t chunkSize{};
|
||||||
modelAsSd0->read(reinterpret_cast<char*>(&chunkSize), sizeof(uint32_t)); // Extract chunk size from istream
|
model.lxfmlData.read(reinterpret_cast<char*>(&chunkSize), sizeof(uint32_t)); // Extract chunk size from istream
|
||||||
|
|
||||||
// Check if good here since if at the end of an sd0 file, this will have eof flagged.
|
// Check if good here since if at the end of an sd0 file, this will have eof flagged.
|
||||||
if (!modelAsSd0->good()) break;
|
if (!model.lxfmlData.good()) break;
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> compressedChunk(new uint8_t[chunkSize]);
|
std::unique_ptr<uint8_t[]> compressedChunk(new uint8_t[chunkSize]);
|
||||||
for (uint32_t i = 0; i < chunkSize; i++) {
|
for (uint32_t i = 0; i < chunkSize; i++) {
|
||||||
compressedChunk[i] = modelAsSd0->get();
|
compressedChunk[i] = model.lxfmlData.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore the valgrind warning about uninitialized values. These are discarded later when we know the actual uncompressed size.
|
// Ignore the valgrind warning about uninitialized values. These are discarded later when we know the actual uncompressed size.
|
||||||
@@ -59,14 +54,14 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
completeUncompressedModel.append((char*)uncompressedChunk.get());
|
completeUncompressedModel.append((char*)uncompressedChunk.get());
|
||||||
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
|
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("BrickByBrickFix", "Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err);
|
LOG("Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, model.id, err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chunkCount++;
|
chunkCount++;
|
||||||
}
|
}
|
||||||
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
|
std::unique_ptr<tinyxml2::XMLDocument> document = std::make_unique<tinyxml2::XMLDocument>();
|
||||||
if (!document) {
|
if (!document) {
|
||||||
Game::logger->Log("BrickByBrickFix", "Failed to initialize tinyxml document. Aborting.");
|
LOG("Failed to initialize tinyxml document. Aborting.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,28 +70,20 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
"</LXFML>",
|
"</LXFML>",
|
||||||
completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos
|
completeUncompressedModel.length() >= 15 ? completeUncompressedModel.length() - 15 : 0) == std::string::npos
|
||||||
) {
|
) {
|
||||||
Game::logger->Log("BrickByBrickFix",
|
LOG("Brick-by-brick model %llu will be deleted!", model.id);
|
||||||
"Brick-by-brick model %llu will be deleted!", modelId);
|
Database::Get()->DeleteUgcModelData(model.id);
|
||||||
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
|
||||||
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
|
||||||
ugcModelToDelete->execute();
|
|
||||||
pcModelToDelete->execute();
|
|
||||||
modelsTruncated++;
|
modelsTruncated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("BrickByBrickFix",
|
LOG("Brick-by-brick model %llu will be deleted!", model.id);
|
||||||
"Brick-by-brick model %llu will be deleted!", modelId);
|
Database::Get()->DeleteUgcModelData(model.id);
|
||||||
ugcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
|
||||||
pcModelToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
|
||||||
ugcModelToDelete->execute();
|
|
||||||
pcModelToDelete->execute();
|
|
||||||
modelsTruncated++;
|
modelsTruncated++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Commit();
|
Database::Get()->Commit();
|
||||||
Database::SetAutoCommit(previousCommitValue);
|
Database::Get()->SetAutoCommit(previousCommitValue);
|
||||||
return modelsTruncated;
|
return modelsTruncated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,21 +95,17 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
*/
|
*/
|
||||||
uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
||||||
uint32_t updatedModels = 0;
|
uint32_t updatedModels = 0;
|
||||||
auto modelsToUpdate = GetModelsFromDatabase();
|
auto modelsToUpdate = Database::Get()->GetAllUgcModels();
|
||||||
auto previousAutoCommitState = Database::GetAutoCommit();
|
auto previousAutoCommitState = Database::Get()->GetAutoCommit();
|
||||||
Database::SetAutoCommit(false);
|
Database::Get()->SetAutoCommit(false);
|
||||||
std::unique_ptr<sql::PreparedStatement> insertionStatement(Database::CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
|
for (auto& model : modelsToUpdate) {
|
||||||
while (modelsToUpdate->next()) {
|
|
||||||
int64_t modelId = modelsToUpdate->getInt64(1);
|
|
||||||
std::unique_ptr<sql::Blob> oldLxfml(modelsToUpdate->getBlob(2));
|
|
||||||
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
|
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
|
||||||
// If it does, convert it to sd0.
|
// If it does, convert it to sd0.
|
||||||
if (oldLxfml->get() == 0x78 && oldLxfml->get() == 0xDA) {
|
if (model.lxfmlData.get() == 0x78 && model.lxfmlData.get() == 0xDA) {
|
||||||
|
|
||||||
// Get and save size of zlib compressed chunk.
|
// Get and save size of zlib compressed chunk.
|
||||||
oldLxfml->seekg(0, std::ios::end);
|
model.lxfmlData.seekg(0, std::ios::end);
|
||||||
uint32_t oldLxfmlSize = static_cast<uint32_t>(oldLxfml->tellg());
|
uint32_t oldLxfmlSize = static_cast<uint32_t>(model.lxfmlData.tellg());
|
||||||
oldLxfml->seekg(0);
|
model.lxfmlData.seekg(0);
|
||||||
|
|
||||||
// Allocate 9 extra bytes. 5 for sd0 magic, 4 for the only zlib compressed size.
|
// Allocate 9 extra bytes. 5 for sd0 magic, 4 for the only zlib compressed size.
|
||||||
uint32_t oldLxfmlSizeWithHeader = oldLxfmlSize + 9;
|
uint32_t oldLxfmlSizeWithHeader = oldLxfmlSize + 9;
|
||||||
@@ -130,36 +113,27 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
|||||||
|
|
||||||
WriteSd0Magic(sd0ConvertedModel.get(), oldLxfmlSize);
|
WriteSd0Magic(sd0ConvertedModel.get(), oldLxfmlSize);
|
||||||
for (uint32_t i = 9; i < oldLxfmlSizeWithHeader; i++) {
|
for (uint32_t i = 9; i < oldLxfmlSizeWithHeader; i++) {
|
||||||
sd0ConvertedModel.get()[i] = oldLxfml->get();
|
sd0ConvertedModel.get()[i] = model.lxfmlData.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string outputString(sd0ConvertedModel.get(), oldLxfmlSizeWithHeader);
|
std::string outputString(sd0ConvertedModel.get(), oldLxfmlSizeWithHeader);
|
||||||
std::istringstream outputStringStream(outputString);
|
std::istringstream outputStringStream(outputString);
|
||||||
|
|
||||||
insertionStatement->setBlob(1, static_cast<std::istream*>(&outputStringStream));
|
|
||||||
insertionStatement->setInt64(2, modelId);
|
|
||||||
try {
|
try {
|
||||||
insertionStatement->executeUpdate();
|
Database::Get()->UpdateUgcModelData(model.id, outputStringStream);
|
||||||
Game::logger->Log("BrickByBrickFix", "Updated model %i to sd0", modelId);
|
LOG("Updated model %i to sd0", model.id);
|
||||||
updatedModels++;
|
updatedModels++;
|
||||||
} catch (sql::SQLException exception) {
|
} catch (sql::SQLException exception) {
|
||||||
Game::logger->Log(
|
LOG("Failed to update model %i. This model should be inspected manually to see why."
|
||||||
"BrickByBrickFix",
|
"The database error is %s", model.id, exception.what());
|
||||||
"Failed to update model %i. This model should be inspected manually to see why."
|
|
||||||
"The database error is %s", modelId, exception.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Database::Commit();
|
Database::Get()->Commit();
|
||||||
Database::SetAutoCommit(previousAutoCommitState);
|
Database::Get()->SetAutoCommit(previousAutoCommitState);
|
||||||
return updatedModels;
|
return updatedModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<sql::ResultSet> GetModelsFromDatabase() {
|
|
||||||
std::unique_ptr<sql::PreparedStatement> modelsRawDataQuery(Database::CreatePreppedStmt("SELECT id, lxfml FROM ugc;"));
|
|
||||||
return std::unique_ptr<sql::ResultSet>(modelsRawDataQuery->executeQuery());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Writes sd0 magic at the front of a char*
|
* @brief Writes sd0 magic at the front of a char*
|
||||||
*
|
*
|
||||||
@@ -175,6 +149,6 @@ void WriteSd0Magic(char* input, uint32_t chunkSize) {
|
|||||||
*reinterpret_cast<uint32_t*>(input + 5) = chunkSize; // Write the integer to the character array
|
*reinterpret_cast<uint32_t*>(input + 5) = chunkSize; // Write the integer to the character array
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckSd0Magic(sql::Blob* streamToCheck) {
|
bool CheckSd0Magic(std::istream& streamToCheck) {
|
||||||
return streamToCheck->get() == 's' && streamToCheck->get() == 'd' && streamToCheck->get() == '0' && streamToCheck->get() == 0x01 && streamToCheck->get() == 0xFF;
|
return streamToCheck.get() == 's' && streamToCheck.get() == 'd' && streamToCheck.get() == '0' && streamToCheck.get() == 0x01 && streamToCheck.get() == 0xFF;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set(DCOMMON_SOURCES
|
|||||||
"BinaryIO.cpp"
|
"BinaryIO.cpp"
|
||||||
"dConfig.cpp"
|
"dConfig.cpp"
|
||||||
"Diagnostics.cpp"
|
"Diagnostics.cpp"
|
||||||
"dLogger.cpp"
|
"Logger.cpp"
|
||||||
"GeneralUtils.cpp"
|
"GeneralUtils.cpp"
|
||||||
"LDFFormat.cpp"
|
"LDFFormat.cpp"
|
||||||
"MD5.cpp"
|
"MD5.cpp"
|
||||||
@@ -12,7 +12,7 @@ set(DCOMMON_SOURCES
|
|||||||
"NiPoint3.cpp"
|
"NiPoint3.cpp"
|
||||||
"NiQuaternion.cpp"
|
"NiQuaternion.cpp"
|
||||||
"SHA512.cpp"
|
"SHA512.cpp"
|
||||||
"Type.cpp"
|
"Demangler.cpp"
|
||||||
"ZCompression.cpp"
|
"ZCompression.cpp"
|
||||||
"BrickByBrickFix.cpp"
|
"BrickByBrickFix.cpp"
|
||||||
"BinaryPathFinder.cpp"
|
"BinaryPathFinder.cpp"
|
||||||
|
|||||||
29
dCommon/Demangler.cpp
Normal file
29
dCommon/Demangler.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#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__
|
||||||
9
dCommon/Demangler.h
Normal file
9
dCommon/Demangler.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "Diagnostics.h"
|
#include "Diagnostics.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
// If we're on Win32, we'll include our minidump writer
|
// If we're on Win32, we'll include our minidump writer
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <Dbghelp.h>
|
#include <Dbghelp.h>
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
void make_minidump(EXCEPTION_POINTERS* e) {
|
void make_minidump(EXCEPTION_POINTERS* e) {
|
||||||
auto hDbgHelp = LoadLibraryA("dbghelp");
|
auto hDbgHelp = LoadLibraryA("dbghelp");
|
||||||
@@ -28,7 +28,7 @@ void make_minidump(EXCEPTION_POINTERS* e) {
|
|||||||
"_%4d%02d%02d_%02d%02d%02d.dmp",
|
"_%4d%02d%02d_%02d%02d%02d.dmp",
|
||||||
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
|
t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
|
||||||
}
|
}
|
||||||
Game::logger->Log("Diagnostics", "Creating crash dump %s", name);
|
LOG("Creating crash dump %s", name);
|
||||||
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
@@ -83,7 +83,7 @@ struct bt_ctx {
|
|||||||
|
|
||||||
static inline void Bt(struct backtrace_state* state) {
|
static inline void Bt(struct backtrace_state* state) {
|
||||||
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
|
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
|
||||||
Game::logger->Log("Diagnostics", "backtrace is enabled, crash dump located at %s", fileName.c_str());
|
LOG("backtrace is enabled, crash dump located at %s", fileName.c_str());
|
||||||
FILE* file = fopen(fileName.c_str(), "w+");
|
FILE* file = fopen(fileName.c_str(), "w+");
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
backtrace_print(state, 2, file);
|
backtrace_print(state, 2, file);
|
||||||
@@ -107,7 +107,7 @@ static void ErrorCallback(void* data, const char* msg, int errnum) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Type.h"
|
#include "Demangler.h"
|
||||||
|
|
||||||
void GenerateDump() {
|
void GenerateDump() {
|
||||||
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
std::string cmd = "sudo gcore " + std::to_string(getpid());
|
||||||
@@ -118,55 +118,56 @@ void CatchUnhandled(int sig) {
|
|||||||
#ifndef __include_backtrace__
|
#ifndef __include_backtrace__
|
||||||
|
|
||||||
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
|
std::string fileName = Diagnostics::GetOutDirectory() + "crash_" + Diagnostics::GetProcessName() + "_" + std::to_string(getpid()) + ".log";
|
||||||
Game::logger->Log("Diagnostics", "Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
|
LOG("Encountered signal %i, creating crash dump %s", sig, fileName.c_str());
|
||||||
if (Diagnostics::GetProduceMemoryDump()) {
|
if (Diagnostics::GetProduceMemoryDump()) {
|
||||||
GenerateDump();
|
GenerateDump();
|
||||||
}
|
}
|
||||||
|
constexpr uint8_t MaxStackTrace = 32;
|
||||||
void* array[10];
|
void* array[MaxStackTrace];
|
||||||
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, 10);
|
size = backtrace(array, MaxStackTrace);
|
||||||
|
|
||||||
#if defined(__GNUG__) and defined(__dynamic)
|
# if defined(__GNUG__)
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
|
FILE* file = fopen(fileName.c_str(), "w+");
|
||||||
|
if (file != NULL) {
|
||||||
|
fprintf(file, "Error: signal %d:\n", sig);
|
||||||
|
}
|
||||||
// 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]' and extract the function name
|
// Take a string like './WorldServer(_ZN19SlashCommandHandler17HandleChatCommandERKSbIDsSt11char_traitsIDsESaIDsEEP6EntityRK13SystemAddress+0x6187) [0x55869c44ecf7]'
|
||||||
|
// 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 = demangle(functionName.c_str());
|
demangled = Demangler::Demangle(demangled.c_str());
|
||||||
|
|
||||||
if (demangled.empty()) {
|
// If the demangled string is not empty, then we can replace the mangled string with the demangled one
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, demangled.c_str());
|
if (!demangled.empty()) {
|
||||||
} else {
|
demangled.push_back('(');
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
demangled += functionName.substr(end);
|
||||||
|
functionName = demangled;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Game::logger->Log("Diagnostics", "[%02zu] %s", i, functionName.c_str());
|
|
||||||
|
LOG("[%02zu] %s", i, functionName.c_str());
|
||||||
|
if (file != NULL) {
|
||||||
|
fprintf(file, "[%02zu] %s\n", i, functionName.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
# else // defined(__GNUG__)
|
||||||
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
backtrace_symbols_fd(array, size, STDOUT_FILENO);
|
||||||
#endif
|
# endif // defined(__GNUG__)
|
||||||
|
|
||||||
FILE* file = fopen(fileName.c_str(), "w+");
|
#else // __include_backtrace__
|
||||||
if (file != NULL) {
|
|
||||||
// print out all the frames to stderr
|
|
||||||
fprintf(file, "Error: signal %d:\n", sig);
|
|
||||||
backtrace_symbols_fd(array, size, fileno(file));
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
struct backtrace_state* state = backtrace_create_state(
|
struct backtrace_state* state = backtrace_create_state(
|
||||||
Diagnostics::GetProcessFileName().c_str(),
|
Diagnostics::GetProcessFileName().c_str(),
|
||||||
@@ -177,7 +178,7 @@ void CatchUnhandled(int sig) {
|
|||||||
struct bt_ctx ctx = { state, 0 };
|
struct bt_ctx ctx = { state, 0 };
|
||||||
Bt(state);
|
Bt(state);
|
||||||
|
|
||||||
#endif
|
#endif // __include_backtrace__
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "CDClientDatabase.h"
|
#include "CDClientDatabase.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
|
|
||||||
#include "eSqliteDataType.h"
|
#include "eSqliteDataType.h"
|
||||||
@@ -44,7 +44,7 @@ bool FdbToSqlite::Convert::ConvertDatabase(AssetMemoryBuffer& buffer) {
|
|||||||
|
|
||||||
CDClientDatabase::ExecuteQuery("COMMIT;");
|
CDClientDatabase::ExecuteQuery("COMMIT;");
|
||||||
} catch (CppSQLite3Exception& e) {
|
} catch (CppSQLite3Exception& e) {
|
||||||
Game::logger->Log("FdbToSqlite", "Encountered error %s converting FDB to SQLite", e.errorMessage());
|
LOG("Encountered error %s converting FDB to SQLite", e.errorMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
class dServer;
|
class dServer;
|
||||||
class dLogger;
|
class Logger;
|
||||||
class InstanceManager;
|
class InstanceManager;
|
||||||
class dChatFilter;
|
class dChatFilter;
|
||||||
class dConfig;
|
class dConfig;
|
||||||
@@ -12,9 +12,10 @@ class AssetManager;
|
|||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
class EntityManager;
|
class EntityManager;
|
||||||
class dZoneManager;
|
class dZoneManager;
|
||||||
|
class PlayerContainer;
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
extern dLogger* logger;
|
extern Logger* logger;
|
||||||
extern dServer* server;
|
extern dServer* server;
|
||||||
extern InstanceManager* im;
|
extern InstanceManager* im;
|
||||||
extern dChatFilter* chatFilter;
|
extern dChatFilter* chatFilter;
|
||||||
@@ -26,4 +27,5 @@ namespace Game {
|
|||||||
extern bool shouldShutdown;
|
extern bool shouldShutdown;
|
||||||
extern EntityManager* entityManager;
|
extern EntityManager* entityManager;
|
||||||
extern dZoneManager* zoneManager;
|
extern dZoneManager* zoneManager;
|
||||||
|
extern PlayerContainer playerContainer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
enum eInventoryType : uint32_t;
|
enum eInventoryType : uint32_t;
|
||||||
enum class eObjectBits : size_t;
|
enum class eObjectBits : size_t;
|
||||||
@@ -126,6 +126,11 @@ 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);
|
||||||
@@ -146,6 +151,11 @@ namespace GeneralUtils {
|
|||||||
return std::stod(value);
|
return std::stod(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline uint16_t Parse(const char* value) {
|
||||||
|
return std::stoul(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline uint32_t Parse(const char* value) {
|
inline uint32_t Parse(const char* value) {
|
||||||
return std::stoul(value);
|
return std::stoul(value);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
// C++
|
// C++
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@@ -48,7 +48,7 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
try {
|
try {
|
||||||
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
|
type = static_cast<eLDFType>(strtol(ldfTypeAndValue.first.data(), &storage, 10));
|
||||||
} catch (std::exception) {
|
} catch (std::exception) {
|
||||||
Game::logger->Log("LDFFormat", "Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
|
LOG("Attempted to process invalid ldf type (%s) from string (%s)", ldfTypeAndValue.first.data(), format.data());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,35 +61,33 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_S32: {
|
case LDF_TYPE_S32: {
|
||||||
try {
|
int32_t data;
|
||||||
int32_t data = static_cast<int32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<int32_t>(key, data);
|
LOG("Warning: Attempted to process invalid int32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
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: {
|
||||||
try {
|
float data;
|
||||||
float data = strtof(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<float>(key, data);
|
LOG("Warning: Attempted to process invalid float value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
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: {
|
||||||
try {
|
double data;
|
||||||
double data = strtod(ldfTypeAndValue.second.data(), &storage);
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<double>(key, data);
|
LOG("Warning: Attempted to process invalid double value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,10 +100,8 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = 0;
|
data = 0;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<uint32_t>(strtoul(ldfTypeAndValue.second.data(), &storage, 10));
|
LOG("Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid uint32 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,10 +118,8 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
} else if (ldfTypeAndValue.second == "false") {
|
} else if (ldfTypeAndValue.second == "false") {
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
data = static_cast<bool>(strtol(ldfTypeAndValue.second.data(), &storage, 10));
|
LOG("Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid bool value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,24 +129,22 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_U64: {
|
case LDF_TYPE_U64: {
|
||||||
try {
|
uint64_t data;
|
||||||
uint64_t data = static_cast<uint64_t>(strtoull(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<uint64_t>(key, data);
|
LOG("Warning: Attempted to process invalid uint64 value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
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: {
|
||||||
try {
|
LWOOBJID data;
|
||||||
LWOOBJID data = static_cast<LWOOBJID>(strtoll(ldfTypeAndValue.second.data(), &storage, 10));
|
if (!GeneralUtils::TryParse(ldfTypeAndValue.second.data(), data)) {
|
||||||
returnValue = new LDFData<LWOOBJID>(key, data);
|
LOG("Warning: Attempted to process invalid LWOOBJID value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
} catch (std::exception) {
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,12 +155,12 @@ LDFBaseData* LDFBaseData::DataFromString(const std::string_view& format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LDF_TYPE_UNKNOWN: {
|
case LDF_TYPE_UNKNOWN: {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
LOG("Warning: Attempted to process invalid unknown value (%s) from string (%s)", ldfTypeAndValue.second.data(), format.data());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
Game::logger->Log("LDFFormat", "Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
|
LOG("Warning: Attempted to process invalid LDF type (%d) from string (%s)", type, format.data());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
96
dCommon/Logger.cpp
Normal file
96
dCommon/Logger.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ctime>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
Writer::~Writer() {
|
||||||
|
// Dont try to close stdcout...
|
||||||
|
if (!m_Outfile || m_IsConsoleWriter) return;
|
||||||
|
|
||||||
|
fclose(m_Outfile);
|
||||||
|
m_Outfile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Writer::Log(const char* time, const char* message) {
|
||||||
|
if (!m_Outfile) return;
|
||||||
|
|
||||||
|
fputs(time, m_Outfile);
|
||||||
|
fputs(message, m_Outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Writer::Flush() {
|
||||||
|
if (!m_Outfile) return;
|
||||||
|
fflush(m_Outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileWriter::FileWriter(const char* outpath) {
|
||||||
|
m_Outfile = fopen(outpath, "wt");
|
||||||
|
if (!m_Outfile) printf("Couldn't open %s for writing!\n", outpath);
|
||||||
|
m_Outpath = outpath;
|
||||||
|
m_IsConsoleWriter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsoleWriter::ConsoleWriter(bool enabled) {
|
||||||
|
m_Enabled = enabled;
|
||||||
|
m_Outfile = stdout;
|
||||||
|
m_IsConsoleWriter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::Logger(const std::string& outpath, bool logToConsole, bool logDebugStatements) {
|
||||||
|
m_logDebugStatements = logDebugStatements;
|
||||||
|
std::filesystem::path outpathPath(outpath);
|
||||||
|
if (!std::filesystem::exists(outpathPath.parent_path())) std::filesystem::create_directories(outpathPath.parent_path());
|
||||||
|
m_Writers.push_back(std::make_unique<FileWriter>(outpath));
|
||||||
|
m_Writers.push_back(std::make_unique<ConsoleWriter>(logToConsole));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::vLog(const char* format, va_list args) {
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm* time = localtime(&t);
|
||||||
|
char timeStr[70];
|
||||||
|
strftime(timeStr, sizeof(timeStr), "[%d-%m-%y %H:%M:%S ", time);
|
||||||
|
char message[2048];
|
||||||
|
vsnprintf(message, 2048, format, args);
|
||||||
|
for (const auto& writer : m_Writers) {
|
||||||
|
writer->Log(timeStr, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::Log(const char* className, const char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
std::string log = std::string(className) + "] " + std::string(format) + "\n";
|
||||||
|
va_start(args, format);
|
||||||
|
vLog(log.c_str(), args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::LogDebug(const char* className, const char* format, ...) {
|
||||||
|
if (!m_logDebugStatements) return;
|
||||||
|
va_list args;
|
||||||
|
std::string log = std::string(className) + "] " + std::string(format) + "\n";
|
||||||
|
va_start(args, format);
|
||||||
|
vLog(log.c_str(), args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::Flush() {
|
||||||
|
for (const auto& writer : m_Writers) {
|
||||||
|
writer->Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::SetLogToConsole(bool logToConsole) {
|
||||||
|
for (const auto& writer : m_Writers) {
|
||||||
|
if (writer->IsConsoleWriter()) writer->SetEnabled(logToConsole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Logger::GetLogToConsole() const {
|
||||||
|
bool toReturn = false;
|
||||||
|
for (const auto& writer : m_Writers) {
|
||||||
|
if (writer->IsConsoleWriter()) toReturn |= writer->GetEnabled();
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
89
dCommon/Logger.h
Normal file
89
dCommon/Logger.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define STRINGIFY_IMPL(x) #x
|
||||||
|
|
||||||
|
#define STRINGIFY(x) STRINGIFY_IMPL(x)
|
||||||
|
|
||||||
|
#define GET_FILE_NAME(x, y) GetFileNameFromAbsolutePath(__FILE__ x y)
|
||||||
|
|
||||||
|
#define FILENAME_AND_LINE GET_FILE_NAME(":", STRINGIFY(__LINE__))
|
||||||
|
|
||||||
|
// Calculate the filename at compile time from the path.
|
||||||
|
// We just do this by scanning the path for the last '/' or '\' character and returning the string after it.
|
||||||
|
constexpr const char* GetFileNameFromAbsolutePath(const char* path) {
|
||||||
|
const char* file = path;
|
||||||
|
while (*path) {
|
||||||
|
char nextChar = *path++;
|
||||||
|
if (nextChar == '/' || nextChar == '\\') {
|
||||||
|
file = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These have to have a constexpr variable to store the filename_and_line result in a local variable otherwise
|
||||||
|
// they will not be valid constexpr and will be evaluated at runtime instead of compile time!
|
||||||
|
// The full string is still stored in the binary, however the offset of the filename in the absolute paths
|
||||||
|
// is used in the instruction instead of the start of the absolute path.
|
||||||
|
#define LOG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->Log(str, message, ##__VA_ARGS__); } while(0)
|
||||||
|
#define LOG_DEBUG(message, ...) do { auto str = FILENAME_AND_LINE; Game::logger->LogDebug(str, message, ##__VA_ARGS__); } while(0)
|
||||||
|
|
||||||
|
// Writer class for writing data to files.
|
||||||
|
class Writer {
|
||||||
|
public:
|
||||||
|
Writer(bool enabled = true) : m_Enabled(enabled) {};
|
||||||
|
virtual ~Writer();
|
||||||
|
|
||||||
|
virtual void Log(const char* time, const char* message);
|
||||||
|
virtual void Flush();
|
||||||
|
|
||||||
|
void SetEnabled(bool disabled) { m_Enabled = disabled; }
|
||||||
|
bool GetEnabled() const { return m_Enabled; }
|
||||||
|
|
||||||
|
bool IsConsoleWriter() { return m_IsConsoleWriter; }
|
||||||
|
public:
|
||||||
|
bool m_Enabled = true;
|
||||||
|
bool m_IsConsoleWriter = false;
|
||||||
|
FILE* m_Outfile;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FileWriter class for writing data to a file on a disk.
|
||||||
|
class FileWriter : public Writer {
|
||||||
|
public:
|
||||||
|
FileWriter(const char* outpath);
|
||||||
|
FileWriter(const std::string& outpath) : FileWriter(outpath.c_str()) {};
|
||||||
|
private:
|
||||||
|
std::string m_Outpath;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ConsoleWriter class for writing data to the console.
|
||||||
|
class ConsoleWriter : public Writer {
|
||||||
|
public:
|
||||||
|
ConsoleWriter(bool enabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
public:
|
||||||
|
Logger() = delete;
|
||||||
|
Logger(const std::string& outpath, bool logToConsole, bool logDebugStatements);
|
||||||
|
|
||||||
|
void Log(const char* filenameAndLine, const char* format, ...);
|
||||||
|
void LogDebug(const char* filenameAndLine, const char* format, ...);
|
||||||
|
|
||||||
|
void Flush();
|
||||||
|
|
||||||
|
bool GetLogToConsole() const;
|
||||||
|
void SetLogToConsole(bool logToConsole);
|
||||||
|
|
||||||
|
void SetLogDebugStatements(bool logDebugStatements) { m_logDebugStatements = logDebugStatements; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void vLog(const char* format, va_list args);
|
||||||
|
|
||||||
|
bool m_logDebugStatements;
|
||||||
|
std::vector<std::unique_ptr<Writer>> m_Writers;
|
||||||
|
};
|
||||||
@@ -136,6 +136,13 @@ NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
|
|||||||
return *this;
|
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 {
|
||||||
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
|
return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z);
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ public:
|
|||||||
//! Operator for addition of vectors
|
//! Operator for addition of vectors
|
||||||
NiPoint3& operator+=(const NiPoint3& point);
|
NiPoint3& operator+=(const NiPoint3& point);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#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
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#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());
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
delete m_Base;
|
free(m_Base);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct PackRecord {
|
struct PackRecord {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "PackIndex.h"
|
#include "PackIndex.h"
|
||||||
#include "BinaryIO.h"
|
#include "BinaryIO.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dLogger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
PackIndex::PackIndex(const std::filesystem::path& filePath) {
|
PackIndex::PackIndex(const std::filesystem::path& filePath) {
|
||||||
m_FileStream = std::ifstream(filePath / "versions" / "primary.pki", std::ios::in | std::ios::binary);
|
m_FileStream = std::ifstream(filePath / "versions" / "primary.pki", std::ios::in | std::ios::binary);
|
||||||
@@ -34,7 +34,7 @@ PackIndex::PackIndex(const std::filesystem::path& filePath) {
|
|||||||
m_PackFileIndices.push_back(packFileIndex);
|
m_PackFileIndices.push_back(packFileIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::logger->Log("PackIndex", "Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
|
LOG("Loaded pack catalog with %i pack files and %i files", m_PackPaths.size(), m_PackFileIndices.size());
|
||||||
|
|
||||||
for (auto& item : m_PackPaths) {
|
for (auto& item : m_PackPaths) {
|
||||||
std::replace(item.begin(), item.end(), '\\', '/');
|
std::replace(item.begin(), item.end(), '\\', '/');
|
||||||
|
|||||||
@@ -38,13 +38,11 @@ const std::string& dConfig::GetValue(std::string key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dConfig::ProcessLine(const std::string& line) {
|
void dConfig::ProcessLine(const std::string& line) {
|
||||||
auto splitLine = GeneralUtils::SplitString(line, '=');
|
auto splitLoc = line.find('=');
|
||||||
|
auto key = line.substr(0, splitLoc);
|
||||||
if (splitLine.size() != 2) return;
|
auto value = line.substr(splitLoc + 1);
|
||||||
|
|
||||||
//Make sure that on Linux, we remove special characters:
|
//Make sure that on Linux, we remove special characters:
|
||||||
auto& key = splitLine.at(0);
|
|
||||||
auto& value = splitLine.at(1);
|
|
||||||
if (!value.empty() && value.at(value.size() - 1) == '\r') value.erase(value.size() - 1);
|
if (!value.empty() && value.at(value.size() - 1) == '\r') value.erase(value.size() - 1);
|
||||||
|
|
||||||
if (this->m_ConfigValues.find(key) != this->m_ConfigValues.end()) return;
|
if (this->m_ConfigValues.find(key) != this->m_ConfigValues.end()) return;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#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
|
||||||
|
|
||||||
@@ -32,7 +33,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 PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER BitStreamUtils::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);
|
||||||
|
|
||||||
|
|||||||
@@ -1152,7 +1152,7 @@ enum class eGameMessageType : uint16_t {
|
|||||||
COLLISION_POINT_REMOVED = 1269,
|
COLLISION_POINT_REMOVED = 1269,
|
||||||
SET_ATTACHED = 1270,
|
SET_ATTACHED = 1270,
|
||||||
SET_DESTROYABLE_MODEL_BRICKS = 1271,
|
SET_DESTROYABLE_MODEL_BRICKS = 1271,
|
||||||
VEHICLE_SET_POWERSLIDE_LOCK_WHEELS = 1273,
|
VEHICLE_SET_POWERSLIDE_LOCK_WHEELS = 1272,
|
||||||
VEHICLE_SET_WHEEL_LOCK_STATE = 1273,
|
VEHICLE_SET_WHEEL_LOCK_STATE = 1273,
|
||||||
SHOW_HEALTH_BAR = 1274,
|
SHOW_HEALTH_BAR = 1274,
|
||||||
GET_SHOWS_HEALTH_BAR = 1275,
|
GET_SHOWS_HEALTH_BAR = 1275,
|
||||||
|
|||||||
@@ -27,20 +27,6 @@ enum class ePermissionMap : uint64_t {
|
|||||||
* The character has restricted chat access, bit 6.
|
* The character has restricted chat access, bit 6.
|
||||||
*/
|
*/
|
||||||
RestrictedChatAccess = 0x1 << 6,
|
RestrictedChatAccess = 0x1 << 6,
|
||||||
|
|
||||||
//
|
|
||||||
// Combined permissions
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The character is marked as 'old', restricted from trade and mail.
|
|
||||||
*/
|
|
||||||
Old = RestrictedTradeAccess | RestrictedMailAccess,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The character is soft banned, restricted from trade, mail, and chat.
|
|
||||||
*/
|
|
||||||
SoftBanned = RestrictedTradeAccess | RestrictedMailAccess | RestrictedChatAccess,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__EPERMISSIONMAP__H__
|
#endif //!__EPERMISSIONMAP__H__
|
||||||
|
|||||||
@@ -166,7 +166,8 @@ enum ePlayerFlag : int32_t {
|
|||||||
NJ_LIGHTNING_SPINJITZU = 2031,
|
NJ_LIGHTNING_SPINJITZU = 2031,
|
||||||
NJ_ICE_SPINJITZU = 2032,
|
NJ_ICE_SPINJITZU = 2032,
|
||||||
NJ_FIRE_SPINJITZU = 2033,
|
NJ_FIRE_SPINJITZU = 2033,
|
||||||
NJ_WU_SHOW_DAILY_CHEST = 2099
|
NJ_WU_SHOW_DAILY_CHEST = 2099,
|
||||||
|
DLU_SKIP_CINEMATICS = 1'000'000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__EPLAYERFLAG__H__
|
#endif //!__EPLAYERFLAG__H__
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
PLATFORM_BOUNDARY,
|
PLATFORM_BOUNDARY,
|
||||||
MODULE,
|
MODULE,
|
||||||
ARCADE,
|
ARCADE,
|
||||||
VEHICLE_PHYSICS, // Havok demo based
|
HAVOK_VEHICLE_PHYSICS,
|
||||||
MOVEMENT_AI,
|
MOVEMENT_AI,
|
||||||
EXHIBIT,
|
EXHIBIT,
|
||||||
OVERHEAD_ICON,
|
OVERHEAD_ICON,
|
||||||
@@ -50,7 +50,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
PROPERTY_ENTRANCE,
|
PROPERTY_ENTRANCE,
|
||||||
FX,
|
FX,
|
||||||
PROPERTY_MANAGEMENT,
|
PROPERTY_MANAGEMENT,
|
||||||
VEHICLE_PHYSICS_NEW, // internal physics based on havok
|
VEHICLE_PHYSICS,
|
||||||
PHYSICS_SYSTEM,
|
PHYSICS_SYSTEM,
|
||||||
QUICK_BUILD,
|
QUICK_BUILD,
|
||||||
SWITCH,
|
SWITCH,
|
||||||
@@ -101,7 +101,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
TRADE,
|
TRADE,
|
||||||
USER_CONTROL,
|
USER_CONTROL,
|
||||||
IGNORE_LIST,
|
IGNORE_LIST,
|
||||||
ROCKET_LAUNCH_LUP,
|
MULTI_ZONE_ENTRANCE,
|
||||||
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,
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ enum class eWorldMessageType : uint32_t {
|
|||||||
HANDLE_FUNNESS,
|
HANDLE_FUNNESS,
|
||||||
FAKE_PRG_CSR_MESSAGE,
|
FAKE_PRG_CSR_MESSAGE,
|
||||||
REQUEST_FREE_TRIAL_REFRESH,
|
REQUEST_FREE_TRIAL_REFRESH,
|
||||||
GM_SET_FREE_TRIAL_STATUS
|
GM_SET_FREE_TRIAL_STATUS,
|
||||||
|
UI_HELP_TOP_5 = 91
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__EWORLDMESSAGETYPE__H__
|
#endif //!__EWORLDMESSAGETYPE__H__
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
#include "dLogger.h"
|
|
||||||
|
|
||||||
dLogger::dLogger(const std::string& outpath, bool logToConsole, bool logDebugStatements) {
|
|
||||||
m_logToConsole = logToConsole;
|
|
||||||
m_logDebugStatements = logDebugStatements;
|
|
||||||
m_outpath = outpath;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
mFile = std::ofstream(m_outpath);
|
|
||||||
if (!mFile) { printf("Couldn't open %s for writing!\n", outpath.c_str()); }
|
|
||||||
#else
|
|
||||||
fp = fopen(outpath.c_str(), "wt");
|
|
||||||
if (fp == NULL) { printf("Couldn't open %s for writing!\n", outpath.c_str()); }
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
dLogger::~dLogger() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
mFile.close();
|
|
||||||
#else
|
|
||||||
if (fp != nullptr) {
|
|
||||||
fclose(fp);
|
|
||||||
fp = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::vLog(const char* format, va_list args) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
time_t t = time(NULL);
|
|
||||||
struct tm time;
|
|
||||||
localtime_s(&time, &t);
|
|
||||||
char timeStr[70];
|
|
||||||
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", &time);
|
|
||||||
char message[2048];
|
|
||||||
vsnprintf(message, 2048, format, args);
|
|
||||||
|
|
||||||
if (m_logToConsole) std::cout << "[" << timeStr << "] " << message;
|
|
||||||
mFile << "[" << timeStr << "] " << message;
|
|
||||||
#else
|
|
||||||
time_t t = time(NULL);
|
|
||||||
struct tm* time = localtime(&t);
|
|
||||||
char timeStr[70];
|
|
||||||
strftime(timeStr, sizeof(timeStr), "%d-%m-%y %H:%M:%S", time);
|
|
||||||
char message[2048];
|
|
||||||
vsnprintf(message, 2048, format, args);
|
|
||||||
|
|
||||||
if (m_logToConsole) {
|
|
||||||
fputs("[", stdout);
|
|
||||||
fputs(timeStr, stdout);
|
|
||||||
fputs("] ", stdout);
|
|
||||||
fputs(message, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp != nullptr) {
|
|
||||||
fputs("[", fp);
|
|
||||||
fputs(timeStr, fp);
|
|
||||||
fputs("] ", fp);
|
|
||||||
fputs(message, fp);
|
|
||||||
} else {
|
|
||||||
printf("Logger not initialized!\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::LogBasic(const char* format, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
vLog(format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::LogBasic(const std::string& message) {
|
|
||||||
LogBasic(message.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::Log(const char* className, const char* format, ...) {
|
|
||||||
va_list args;
|
|
||||||
std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
|
|
||||||
va_start(args, format);
|
|
||||||
vLog(log.c_str(), args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::Log(const std::string& className, const std::string& message) {
|
|
||||||
Log(className.c_str(), message.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::LogDebug(const char* className, const char* format, ...) {
|
|
||||||
if (!m_logDebugStatements) return;
|
|
||||||
va_list args;
|
|
||||||
std::string log = "[" + std::string(className) + "] " + std::string(format) + "\n";
|
|
||||||
va_start(args, format);
|
|
||||||
vLog(log.c_str(), args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::LogDebug(const std::string& className, const std::string& message) {
|
|
||||||
LogDebug(className.c_str(), message.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void dLogger::Flush() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
mFile.flush();
|
|
||||||
#else
|
|
||||||
if (fp != nullptr) {
|
|
||||||
std::fflush(fp);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <ctime>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class dLogger {
|
|
||||||
public:
|
|
||||||
dLogger(const std::string& outpath, bool logToConsole, bool logDebugStatements);
|
|
||||||
~dLogger();
|
|
||||||
|
|
||||||
void SetLogToConsole(bool logToConsole) { m_logToConsole = logToConsole; }
|
|
||||||
void SetLogDebugStatements(bool logDebugStatements) { m_logDebugStatements = logDebugStatements; }
|
|
||||||
void vLog(const char* format, va_list args);
|
|
||||||
|
|
||||||
void LogBasic(const std::string& message);
|
|
||||||
void LogBasic(const char* format, ...);
|
|
||||||
void Log(const char* className, const char* format, ...);
|
|
||||||
void Log(const std::string& className, const std::string& message);
|
|
||||||
void LogDebug(const std::string& className, const std::string& message);
|
|
||||||
void LogDebug(const char* className, const char* format, ...);
|
|
||||||
|
|
||||||
void Flush();
|
|
||||||
|
|
||||||
const bool GetIsLoggingToConsole() const { return m_logToConsole; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_logDebugStatements;
|
|
||||||
bool m_logToConsole;
|
|
||||||
std::string m_outpath;
|
|
||||||
std::ofstream mFile;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
//Glorious linux can run with SPEED:
|
|
||||||
FILE* fp = nullptr;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
@@ -13,15 +13,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
//! The CDClient Database namespace
|
||||||
//#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
|
||||||
92
dDatabase/CDClientDatabase/CDClientManager.cpp
Normal file
92
dDatabase/CDClientDatabase/CDClientManager.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#include "CDClientManager.h"
|
||||||
|
#include "CDActivityRewardsTable.h"
|
||||||
|
#include "CDAnimationsTable.h"
|
||||||
|
#include "CDBehaviorParameterTable.h"
|
||||||
|
#include "CDBehaviorTemplateTable.h"
|
||||||
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "CDCurrencyTableTable.h"
|
||||||
|
#include "CDDestructibleComponentTable.h"
|
||||||
|
#include "CDEmoteTable.h"
|
||||||
|
#include "CDInventoryComponentTable.h"
|
||||||
|
#include "CDItemComponentTable.h"
|
||||||
|
#include "CDItemSetsTable.h"
|
||||||
|
#include "CDItemSetSkillsTable.h"
|
||||||
|
#include "CDLevelProgressionLookupTable.h"
|
||||||
|
#include "CDLootMatrixTable.h"
|
||||||
|
#include "CDLootTableTable.h"
|
||||||
|
#include "CDMissionNPCComponentTable.h"
|
||||||
|
#include "CDMissionTasksTable.h"
|
||||||
|
#include "CDMissionsTable.h"
|
||||||
|
#include "CDObjectSkillsTable.h"
|
||||||
|
#include "CDObjectsTable.h"
|
||||||
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
#include "CDRebuildComponentTable.h"
|
||||||
|
#include "CDScriptComponentTable.h"
|
||||||
|
#include "CDSkillBehaviorTable.h"
|
||||||
|
#include "CDZoneTableTable.h"
|
||||||
|
#include "CDVendorComponentTable.h"
|
||||||
|
#include "CDActivitiesTable.h"
|
||||||
|
#include "CDPackageComponentTable.h"
|
||||||
|
#include "CDProximityMonitorComponentTable.h"
|
||||||
|
#include "CDMovementAIComponentTable.h"
|
||||||
|
#include "CDBrickIDTableTable.h"
|
||||||
|
#include "CDRarityTableTable.h"
|
||||||
|
#include "CDMissionEmailTable.h"
|
||||||
|
#include "CDRewardsTable.h"
|
||||||
|
#include "CDPropertyEntranceComponentTable.h"
|
||||||
|
#include "CDPropertyTemplateTable.h"
|
||||||
|
#include "CDFeatureGatingTable.h"
|
||||||
|
#include "CDRailActivatorComponent.h"
|
||||||
|
#include "CDRewardCodesTable.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() {
|
||||||
|
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDComponentsRegistryTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDEmoteTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDInventoryComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDItemComponentTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDItemSetsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDLootMatrixTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDLootTableTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDMissionEmailTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDMissionTasksTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDMissionsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDMovementAIComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDObjectSkillsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase());
|
||||||
|
CDPhysicsComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDPackageComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDPropertyTemplateTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDRarityTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDRewardCodesTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
CDActivitiesTable::CDActivitiesTable(void) {
|
void CDActivitiesTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// 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");
|
||||||
@@ -55,8 +54,3 @@ std::vector<CDActivities> CDActivitiesTable::Query(std::function<bool(CDActiviti
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDActivities> CDActivitiesTable::GetEntries(void) const {
|
|
||||||
return this->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -30,9 +30,10 @@ private:
|
|||||||
std::vector<CDActivities> entries;
|
std::vector<CDActivities> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDActivitiesTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
std::vector<CDActivities> Query(std::function<bool(CDActivities)> predicate);
|
||||||
|
|
||||||
std::vector<CDActivities> GetEntries(void) const;
|
const std::vector<CDActivities>& GetEntries() const { return this->entries; }
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDActivityRewardsTable.h"
|
#include "CDActivityRewardsTable.h"
|
||||||
|
|
||||||
CDActivityRewardsTable::CDActivityRewardsTable(void) {
|
void CDActivityRewardsTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// First, get the size of the table
|
// First, get the size of the table
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
@@ -43,8 +43,3 @@ 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:
|
||||||
CDActivityRewardsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
std::vector<CDActivityRewards> Query(std::function<bool(CDActivityRewards)> predicate);
|
||||||
|
|
||||||
std::vector<CDActivityRewards> GetEntries(void) const;
|
std::vector<CDActivityRewards> GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -2,6 +2,35 @@
|
|||||||
#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,6 +27,7 @@ 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,15 +1,15 @@
|
|||||||
#include "CDBehaviorParameterTable.h"
|
#include "CDBehaviorParameterTable.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|
||||||
uint64_t GetHash(const uint32_t behaviorID, const uint32_t parameterID) {
|
uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
|
||||||
uint64_t hash = behaviorID;
|
uint64_t key = behaviorID;
|
||||||
hash <<= 31U;
|
key <<= 31U;
|
||||||
hash |= parameterID;
|
key |= parameterID;
|
||||||
|
|
||||||
return hash;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBehaviorParameterTable::CDBehaviorParameterTable() {
|
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
|
uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
|
||||||
@@ -21,7 +21,7 @@ CDBehaviorParameterTable::CDBehaviorParameterTable() {
|
|||||||
} else {
|
} else {
|
||||||
parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
|
parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
|
||||||
}
|
}
|
||||||
uint64_t hash = GetHash(behaviorID, parameterId);
|
uint64_t hash = GetKey(behaviorID, parameterId);
|
||||||
float value = tableData.getFloatField("value", -1.0f);
|
float value = tableData.getFloatField("value", -1.0f);
|
||||||
|
|
||||||
m_Entries.insert(std::make_pair(hash, value));
|
m_Entries.insert(std::make_pair(hash, value));
|
||||||
@@ -34,7 +34,7 @@ CDBehaviorParameterTable::CDBehaviorParameterTable() {
|
|||||||
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 = GetHash(behaviorID, parameterID->second);
|
auto hash = GetKey(behaviorID, parameterID->second);
|
||||||
|
|
||||||
// Search for specific parameter
|
// Search for specific parameter
|
||||||
auto it = m_Entries.find(hash);
|
auto it = m_Entries.find(hash);
|
||||||
@@ -45,7 +45,7 @@ std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID
|
|||||||
uint64_t hashBase = behaviorID;
|
uint64_t hashBase = behaviorID;
|
||||||
std::map<std::string, float> returnInfo;
|
std::map<std::string, float> returnInfo;
|
||||||
for (auto& [parameterString, parameterId] : m_ParametersList) {
|
for (auto& [parameterString, parameterId] : m_ParametersList) {
|
||||||
uint64_t hash = GetHash(hashBase, parameterId);
|
uint64_t hash = GetKey(hashBase, parameterId);
|
||||||
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(parameterString, infoCandidate->second));
|
||||||
@@ -12,7 +12,7 @@ private:
|
|||||||
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
|
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:
|
||||||
CDBehaviorParameterTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "CDBehaviorTemplateTable.h"
|
#include "CDBehaviorTemplateTable.h"
|
||||||
|
|
||||||
CDBehaviorTemplateTable::CDBehaviorTemplateTable(void) {
|
void CDBehaviorTemplateTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDBehaviorTemplate> CDBehaviorTemplateTable::GetEntries(void) const {
|
const std::vector<CDBehaviorTemplate>& CDBehaviorTemplateTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +64,3 @@ const CDBehaviorTemplate CDBehaviorTemplateTable::GetByBehaviorID(uint32_t behav
|
|||||||
return entry->second;
|
return entry->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,11 +19,12 @@ 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:
|
||||||
CDBehaviorTemplateTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
std::vector<CDBehaviorTemplate> GetEntries(void) const;
|
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"
|
||||||
|
|
||||||
CDBrickIDTableTable::CDBrickIDTableTable(void) {
|
void CDBrickIDTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDBrickIDTable> CDBrickIDTableTable::GetEntries(void) const {
|
const std::vector<CDBrickIDTable>& CDBrickIDTableTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,9 +21,9 @@ private:
|
|||||||
std::vector<CDBrickIDTable> entries;
|
std::vector<CDBrickIDTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDBrickIDTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
std::vector<CDBrickIDTable> Query(std::function<bool(CDBrickIDTable)> predicate);
|
||||||
|
|
||||||
std::vector<CDBrickIDTable> GetEntries(void) const;
|
const std::vector<CDBrickIDTable>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
void CDComponentsRegistryTable::LoadValuesFromDatabase() {
|
||||||
|
// Now get the data
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDComponentsRegistry entry;
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
|
||||||
|
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(entry.id, 0);
|
||||||
|
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) {
|
||||||
|
auto exists = mappedEntries.find(id);
|
||||||
|
if (exists != mappedEntries.end()) {
|
||||||
|
auto iter = mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
|
return iter == mappedEntries.end() ? defaultValue : iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the data. Get all components of this entity so we dont do a query for each component
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ComponentsRegistry WHERE id = ?;");
|
||||||
|
query.bind(1, static_cast<int32_t>(id));
|
||||||
|
|
||||||
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDComponentsRegistry entry;
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.component_type = static_cast<eReplicaComponentType>(tableData.getIntField("component_type", 0));
|
||||||
|
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);
|
||||||
|
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
mappedEntries.insert_or_assign(id, 0);
|
||||||
|
|
||||||
|
auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
|
||||||
|
|
||||||
|
return iter == this->mappedEntries.end() ? defaultValue : iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
enum class eReplicaComponentType : uint32_t;
|
enum class eReplicaComponentType : uint32_t;
|
||||||
struct CDComponentsRegistry {
|
struct CDComponentsRegistry {
|
||||||
unsigned int id; //!< The LOT is used as the ID
|
unsigned int id; //!< The LOT is used as the ID
|
||||||
@@ -13,9 +15,9 @@ struct CDComponentsRegistry {
|
|||||||
|
|
||||||
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
class CDComponentsRegistryTable : public CDTable<CDComponentsRegistryTable> {
|
||||||
private:
|
private:
|
||||||
std::map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
std::unordered_map<uint64_t, uint32_t> mappedEntries; //id, component_type, component_id
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDComponentsRegistryTable();
|
void LoadValuesFromDatabase();
|
||||||
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0);
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CDCurrencyTableTable.h"
|
#include "CDCurrencyTableTable.h"
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
CDCurrencyTableTable::CDCurrencyTableTable(void) {
|
void CDCurrencyTableTable::LoadValuesFromDatabase() {
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDCurrencyTable> CDCurrencyTableTable::GetEntries(void) const {
|
const std::vector<CDCurrencyTable>& CDCurrencyTableTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@ private:
|
|||||||
std::vector<CDCurrencyTable> entries;
|
std::vector<CDCurrencyTable> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDCurrencyTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
std::vector<CDCurrencyTable> Query(std::function<bool(CDCurrencyTable)> predicate);
|
||||||
|
|
||||||
std::vector<CDCurrencyTable> GetEntries(void) const;
|
const std::vector<CDCurrencyTable>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "CDDestructibleComponentTable.h"
|
#include "CDDestructibleComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDDestructibleComponentTable::LoadValuesFromDatabase() {
|
||||||
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");
|
||||||
@@ -52,7 +50,7 @@ std::vector<CDDestructibleComponent> CDDestructibleComponentTable::Query(std::fu
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDDestructibleComponent> CDDestructibleComponentTable::GetEntries(void) const {
|
const std::vector<CDDestructibleComponent>& CDDestructibleComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ private:
|
|||||||
std::vector<CDDestructibleComponent> entries;
|
std::vector<CDDestructibleComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDDestructibleComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
std::vector<CDDestructibleComponent> Query(std::function<bool(CDDestructibleComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDDestructibleComponent> GetEntries(void) const;
|
const std::vector<CDDestructibleComponent>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
26
dDatabase/CDClientDatabase/CDClientTables/CDEmoteTable.cpp
Normal file
26
dDatabase/CDClientDatabase/CDClientTables/CDEmoteTable.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "CDEmoteTable.h"
|
||||||
|
|
||||||
|
void CDEmoteTableTable::LoadValuesFromDatabase() {
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDEmoteTable entry;
|
||||||
|
entry.ID = tableData.getIntField("id", -1);
|
||||||
|
entry.animationName = tableData.getStringField("animationName", "");
|
||||||
|
entry.iconFilename = tableData.getStringField("iconFilename", "");
|
||||||
|
entry.channel = tableData.getIntField("channel", -1);
|
||||||
|
entry.locked = tableData.getIntField("locked", -1) != 0;
|
||||||
|
entry.localize = tableData.getIntField("localize", -1) != 0;
|
||||||
|
entry.locState = tableData.getIntField("locStatus", -1);
|
||||||
|
entry.gateVersion = tableData.getStringField("gate_version", "");
|
||||||
|
|
||||||
|
entries.insert(std::make_pair(entry.ID, entry));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
|
||||||
|
auto itr = entries.find(id);
|
||||||
|
return itr != entries.end() ? &itr->second : nullptr;
|
||||||
|
}
|
||||||
@@ -28,11 +28,10 @@ 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:
|
||||||
CDEmoteTableTable();
|
void LoadValuesFromDatabase();
|
||||||
~CDEmoteTableTable();
|
|
||||||
// Returns an emote by ID
|
// Returns an emote by ID
|
||||||
CDEmoteTable* GetEmote(int id);
|
CDEmoteTable* GetEmote(int id);
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDFeatureGatingTable.h"
|
#include "CDFeatureGatingTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDFeatureGatingTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -43,9 +42,9 @@ std::vector<CDFeatureGating> CDFeatureGatingTable::Query(std::function<bool(CDFe
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
|
bool CDFeatureGatingTable::FeatureUnlocked(const CDFeatureGating& feature) const {
|
||||||
for (const auto& entry : entries) {
|
for (const auto& entry : entries) {
|
||||||
if (entry.featureName == feature) {
|
if (entry.featureName == feature.featureName && feature >= entry) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +52,7 @@ bool CDFeatureGatingTable::FeatureUnlocked(const std::string& feature) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDFeatureGating> CDFeatureGatingTable::GetEntries(void) const {
|
const std::vector<CDFeatureGating>& CDFeatureGatingTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,6 +9,12 @@ struct CDFeatureGating {
|
|||||||
int32_t current;
|
int32_t current;
|
||||||
int32_t minor;
|
int32_t minor;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
||||||
|
bool operator>=(const CDFeatureGating& b) const {
|
||||||
|
return (this->major > b.major) ||
|
||||||
|
(this->major == b.major && this->current > b.current) ||
|
||||||
|
(this->major == b.major && this->current == b.current && this->minor >= b.minor);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable> {
|
class CDFeatureGatingTable : public CDTable<CDFeatureGatingTable> {
|
||||||
@@ -16,11 +22,12 @@ private:
|
|||||||
std::vector<CDFeatureGating> entries;
|
std::vector<CDFeatureGating> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDFeatureGatingTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// 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 CDFeatureGating& feature) const;
|
||||||
|
|
||||||
std::vector<CDFeatureGating> GetEntries(void) const;
|
const std::vector<CDFeatureGating>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDInventoryComponentTable.h"
|
#include "CDInventoryComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDInventoryComponentTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -42,7 +41,7 @@ std::vector<CDInventoryComponent> CDInventoryComponentTable::Query(std::function
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDInventoryComponent> CDInventoryComponentTable::GetEntries(void) const {
|
const std::vector<CDInventoryComponent>& CDInventoryComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,9 +15,9 @@ private:
|
|||||||
std::vector<CDInventoryComponent> entries;
|
std::vector<CDInventoryComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDInventoryComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
std::vector<CDInventoryComponent> Query(std::function<bool(CDInventoryComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDInventoryComponent> GetEntries(void) const;
|
const std::vector<CDInventoryComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -3,11 +3,7 @@
|
|||||||
|
|
||||||
CDItemComponent CDItemComponentTable::Default = {};
|
CDItemComponent CDItemComponentTable::Default = {};
|
||||||
|
|
||||||
//! Constructor
|
void CDItemComponentTable::LoadValuesFromDatabase() {
|
||||||
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");
|
||||||
@@ -55,13 +51,13 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
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", "");
|
||||||
entry.audioEventUse = tableData.getStringField("audioEventUse", "");
|
UNUSED_COLUMN(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);
|
||||||
entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", "");
|
UNUSED_COLUMN(entry.audioEquipMetaEventSet = tableData.getStringField("audioEquipMetaEventSet", ""));
|
||||||
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
entry.currencyCosts = tableData.getStringField("currencyCosts", "");
|
||||||
entry.ingredientInfo = tableData.getStringField("ingredientInfo", "");
|
UNUSED_COLUMN(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);
|
||||||
@@ -71,7 +67,6 @@ CDItemComponentTable::CDItemComponentTable(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
|
||||||
@@ -80,12 +75,10 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM ItemComponent WHERE id = ?;");
|
||||||
std::stringstream query;
|
query.bind(1, static_cast<int32_t>(skillID));
|
||||||
|
|
||||||
query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(skillID);
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
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;
|
||||||
@@ -144,7 +137,6 @@ 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:
|
||||||
CDItemComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
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,7 +1,6 @@
|
|||||||
#include "CDItemSetSkillsTable.h"
|
#include "CDItemSetSkillsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDItemSetSkillsTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -41,7 +40,7 @@ std::vector<CDItemSetSkills> CDItemSetSkillsTable::Query(std::function<bool(CDIt
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> CDItemSetSkillsTable::GetEntries(void) const {
|
const std::vector<CDItemSetSkills>& CDItemSetSkillsTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,11 +14,11 @@ private:
|
|||||||
std::vector<CDItemSetSkills> entries;
|
std::vector<CDItemSetSkills> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDItemSetSkillsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
std::vector<CDItemSetSkills> Query(std::function<bool(CDItemSetSkills)> predicate);
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> GetEntries(void) const;
|
const std::vector<CDItemSetSkills>& GetEntries() const;
|
||||||
|
|
||||||
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
std::vector<CDItemSetSkills> GetBySkillID(unsigned int SkillSetID);
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDItemSetsTable.h"
|
#include "CDItemSetsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDItemSetsTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -53,7 +52,7 @@ std::vector<CDItemSets> CDItemSetsTable::Query(std::function<bool(CDItemSets)> p
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDItemSets> CDItemSetsTable::GetEntries(void) const {
|
const std::vector<CDItemSets>& CDItemSetsTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,10 +26,10 @@ private:
|
|||||||
std::vector<CDItemSets> entries;
|
std::vector<CDItemSets> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDItemSetsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
std::vector<CDItemSets> Query(std::function<bool(CDItemSets)> predicate);
|
||||||
|
|
||||||
std::vector<CDItemSets> GetEntries(void) const;
|
const std::vector<CDItemSets>& GetEntries(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDLevelProgressionLookupTable.h"
|
#include "CDLevelProgressionLookupTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDLevelProgressionLookupTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -32,7 +31,6 @@ CDLevelProgressionLookupTable::CDLevelProgressionLookupTable(void) {
|
|||||||
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)
|
||||||
@@ -42,8 +40,7 @@ std::vector<CDLevelProgressionLookup> CDLevelProgressionLookupTable::Query(std::
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDLevelProgressionLookup>& CDLevelProgressionLookupTable::GetEntries() const {
|
||||||
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:
|
||||||
CDLevelProgressionLookupTable();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
std::vector<CDLevelProgressionLookup> Query(std::function<bool(CDLevelProgressionLookup)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
const std::vector<CDLevelProgressionLookup>& GetEntries() const;
|
||||||
std::vector<CDLevelProgressionLookup> GetEntries(void) const;
|
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include "CDLootMatrixTable.h"
|
||||||
|
|
||||||
|
CDLootMatrix CDLootMatrixTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
|
CDLootMatrix entry{};
|
||||||
|
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
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM LootMatrix");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
this->entries.reserve(size);
|
||||||
|
|
||||||
|
// Now get the data
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootMatrix");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDLootMatrix entry;
|
||||||
|
uint32_t lootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
|
|
||||||
|
this->entries[lootMatrixIndex].push_back(ReadRow(tableData));
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->entries[matrixId];
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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> {
|
||||||
private:
|
|
||||||
std::vector<CDLootMatrix> entries;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDLootMatrixTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
|
||||||
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
|
|
||||||
|
|
||||||
const std::vector<CDLootMatrix>& GetEntries(void) const;
|
// Gets a matrix by ID or inserts a blank one if none existed.
|
||||||
|
const LootMatrixEntries& GetMatrix(uint32_t matrixId);
|
||||||
|
private:
|
||||||
|
CDLootMatrix ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootMatrixIndex, LootMatrixEntries> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
#include "CDLootTableTable.h"
|
||||||
|
#include "CDClientManager.h"
|
||||||
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "CDItemComponentTable.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
// Sort the tables by their rarity so the highest rarity items are first.
|
||||||
|
void SortTable(LootTableEntries& table) {
|
||||||
|
auto* componentsRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||||
|
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
|
||||||
|
// We modify the table in place so the outer loop keeps track of what is sorted
|
||||||
|
// and the inner loop finds the highest rarity item and swaps it with the current position
|
||||||
|
// of the outer loop.
|
||||||
|
for (auto oldItrOuter = table.begin(); oldItrOuter != table.end(); oldItrOuter++) {
|
||||||
|
auto lootToInsert = oldItrOuter;
|
||||||
|
// Its fine if this starts at 0, even if this doesnt match lootToInsert as the actual highest will
|
||||||
|
// either be found and overwrite these values, or the original is somehow zero and is still the highest rarity.
|
||||||
|
uint32_t highestLootRarity = 0;
|
||||||
|
for (auto oldItrInner = oldItrOuter; oldItrInner != table.end(); oldItrInner++) {
|
||||||
|
uint32_t itemComponentId = componentsRegistryTable->GetByIDAndType(oldItrInner->itemid, eReplicaComponentType::ITEM);
|
||||||
|
uint32_t rarity = itemComponentTable->GetItemComponentByID(itemComponentId).rarity;
|
||||||
|
if (rarity > highestLootRarity) {
|
||||||
|
highestLootRarity = rarity;
|
||||||
|
lootToInsert = oldItrInner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::swap(*oldItrOuter, *lootToInsert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CDLootTable CDLootTableTable::ReadRow(CppSQLite3Query& tableData) const {
|
||||||
|
CDLootTable entry{};
|
||||||
|
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
|
||||||
|
unsigned int size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM LootTable");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
this->entries.reserve(size);
|
||||||
|
|
||||||
|
// Now get the data
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM LootTable");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDLootTable entry;
|
||||||
|
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
|
||||||
|
this->entries[lootTableIndex].push_back(ReadRow(tableData));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
for (auto& [id, table] : this->entries) {
|
||||||
|
SortTable(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
SortTable(this->entries[tableId]);
|
||||||
|
|
||||||
|
return this->entries[tableId];
|
||||||
|
}
|
||||||
@@ -6,20 +6,21 @@
|
|||||||
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:
|
||||||
std::vector<CDLootTable> entries;
|
CDLootTable ReadRow(CppSQLite3Query& tableData) const;
|
||||||
|
std::unordered_map<LootTableIndex, LootTableEntries> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDLootTableTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate);
|
const LootTableEntries& GetTable(uint32_t tableId);
|
||||||
|
|
||||||
const std::vector<CDLootTable>& GetEntries(void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionEmailTable.h"
|
#include "CDMissionEmailTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionEmailTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -48,7 +47,7 @@ std::vector<CDMissionEmail> CDMissionEmailTable::Query(std::function<bool(CDMiss
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDMissionEmail> CDMissionEmailTable::GetEntries(void) const {
|
const std::vector<CDMissionEmail>& CDMissionEmailTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@ private:
|
|||||||
std::vector<CDMissionEmail> entries;
|
std::vector<CDMissionEmail> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionEmailTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
std::vector<CDMissionEmail> Query(std::function<bool(CDMissionEmail)> predicate);
|
||||||
|
|
||||||
std::vector<CDMissionEmail> GetEntries(void) const;
|
const std::vector<CDMissionEmail>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionNPCComponentTable.h"
|
#include "CDMissionNPCComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -45,7 +44,7 @@ std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::Query(std::functi
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDMissionNPCComponent> CDMissionNPCComponentTable::GetEntries(void) const {
|
const std::vector<CDMissionNPCComponent>& CDMissionNPCComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,12 +16,12 @@ private:
|
|||||||
std::vector<CDMissionNPCComponent> entries;
|
std::vector<CDMissionNPCComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionNPCComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDMissionNPCComponent> GetEntries(void) const;
|
const std::vector<CDMissionNPCComponent>& GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMissionTasksTable.h"
|
#include "CDMissionTasksTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionTasksTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -56,16 +55,14 @@ 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) {
|
||||||
CDMissionTasks* task = const_cast<CDMissionTasks*>(&entry);
|
tasks.push_back(&entry);
|
||||||
|
|
||||||
tasks.push_back(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries(void) const {
|
const std::vector<CDMissionTasks>& CDMissionTasksTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,12 +24,12 @@ private:
|
|||||||
std::vector<CDMissionTasks> entries;
|
std::vector<CDMissionTasks> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDMissionTasksTable();
|
void LoadValuesFromDatabase();
|
||||||
// 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(void) const;
|
const std::vector<CDMissionTasks>& GetEntries() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
CDMissions CDMissionsTable::Default = {};
|
CDMissions CDMissionsTable::Default = {};
|
||||||
|
|
||||||
//! Constructor
|
void CDMissionsTable::LoadValuesFromDatabase() {
|
||||||
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:
|
||||||
CDMissionsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
std::vector<CDMissions> Query(std::function<bool(CDMissions)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
const std::vector<CDMissions>& GetEntries(void) const;
|
const std::vector<CDMissions>& GetEntries() const;
|
||||||
|
|
||||||
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
const CDMissions* GetPtrByMissionID(uint32_t missionID) const;
|
||||||
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDMovementAIComponentTable.h"
|
#include "CDMovementAIComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -37,7 +36,6 @@ CDMovementAIComponentTable::CDMovementAIComponentTable(void) {
|
|||||||
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)
|
||||||
@@ -47,8 +45,7 @@ std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::functi
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDMovementAIComponent>& CDMovementAIComponentTable::GetEntries(void) const {
|
||||||
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:
|
||||||
CDMovementAIComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
std::vector<CDMovementAIComponent> Query(std::function<bool(CDMovementAIComponent)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDMovementAIComponent> GetEntries(void) const;
|
const std::vector<CDMovementAIComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDObjectSkillsTable.h"
|
#include "CDObjectSkillsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDObjectSkillsTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -33,7 +32,6 @@ CDObjectSkillsTable::CDObjectSkillsTable(void) {
|
|||||||
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)
|
||||||
@@ -43,7 +41,6 @@ std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObje
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
const std::vector<CDObjectSkills>& CDObjectSkillsTable::GetEntries() const {
|
||||||
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:
|
||||||
CDObjectSkillsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
std::vector<CDObjectSkills> Query(std::function<bool(CDObjectSkills)> predicate);
|
||||||
|
|
||||||
// Gets all the entries in the table
|
// Gets all the entries in the table
|
||||||
std::vector<CDObjectSkills> GetEntries(void) const;
|
const std::vector<CDObjectSkills>& GetEntries() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "CDObjectsTable.h"
|
#include "CDObjectsTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDObjectsTable::LoadValuesFromDatabase() {
|
||||||
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");
|
||||||
@@ -20,25 +18,24 @@ CDObjectsTable::CDObjectsTable(void) {
|
|||||||
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", "");
|
||||||
entry.placeable = tableData.getIntField("placeable", -1);
|
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
entry.description = tableData.getStringField("description", "");
|
UNUSED_COLUMN(entry.description = tableData.getStringField("description", "");)
|
||||||
entry.localize = tableData.getIntField("localize", -1);
|
UNUSED_COLUMN(entry.localize = tableData.getIntField("localize", -1);)
|
||||||
entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);
|
UNUSED_COLUMN(entry.npcTemplateID = tableData.getIntField("npcTemplateID", -1);)
|
||||||
entry.displayName = tableData.getStringField("displayName", "");
|
UNUSED_COLUMN(entry.displayName = tableData.getStringField("displayName", "");)
|
||||||
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
entry.interactionDistance = tableData.getFloatField("interactionDistance", -1.0f);
|
||||||
entry.nametag = tableData.getIntField("nametag", -1);
|
UNUSED_COLUMN(entry.nametag = tableData.getIntField("nametag", -1);)
|
||||||
entry._internalNotes = tableData.getStringField("_internalNotes", "");
|
UNUSED_COLUMN(entry._internalNotes = tableData.getStringField("_internalNotes", "");)
|
||||||
entry.locStatus = tableData.getIntField("locStatus", -1);
|
UNUSED_COLUMN(entry.locStatus = tableData.getIntField("locStatus", -1);)
|
||||||
entry.gate_version = tableData.getStringField("gate_version", "");
|
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
|
||||||
entry.HQ_valid = tableData.getIntField("HQ_valid", -1);
|
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
|
||||||
|
|
||||||
this->entries.insert(std::make_pair(entry.id, entry));
|
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;
|
||||||
}
|
}
|
||||||
@@ -49,12 +46,10 @@ const CDObjects& CDObjectsTable::GetByID(unsigned int LOT) {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
|
||||||
std::stringstream query;
|
query.bind(1, static_cast<int32_t>(LOT));
|
||||||
|
|
||||||
query << "SELECT * FROM Objects WHERE id = " << std::to_string(LOT);
|
auto tableData = query.execQuery();
|
||||||
|
|
||||||
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;
|
||||||
@@ -88,7 +83,6 @@ 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:
|
||||||
CDObjectsTable();
|
void LoadValuesFromDatabase();
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
const CDObjects& GetByID(unsigned int LOT);
|
const CDObjects& GetByID(unsigned int LOT);
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "CDPackageComponentTable.h"
|
#include "CDPackageComponentTable.h"
|
||||||
|
|
||||||
//! Constructor
|
void CDPackageComponentTable::LoadValuesFromDatabase() {
|
||||||
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;
|
||||||
@@ -43,7 +42,7 @@ std::vector<CDPackageComponent> CDPackageComponentTable::Query(std::function<boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Gets all the entries in the table
|
//! Gets all the entries in the table
|
||||||
std::vector<CDPackageComponent> CDPackageComponentTable::GetEntries(void) const {
|
const std::vector<CDPackageComponent>& CDPackageComponentTable::GetEntries() const {
|
||||||
return this->entries;
|
return this->entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ private:
|
|||||||
std::vector<CDPackageComponent> entries;
|
std::vector<CDPackageComponent> entries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CDPackageComponentTable(void);
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
std::vector<CDPackageComponent> Query(std::function<bool(CDPackageComponent)> predicate);
|
||||||
|
|
||||||
std::vector<CDPackageComponent> GetEntries(void) const;
|
const std::vector<CDPackageComponent>& GetEntries() const;
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
|
void CDPhysicsComponentTable::LoadValuesFromDatabase() {
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDPhysicsComponent entry;
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
entry.bStatic = tableData.getIntField("static", -1) != 0;
|
||||||
|
entry.physicsAsset = tableData.getStringField("physics_asset", "");
|
||||||
|
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
||||||
|
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
||||||
|
entry.speed = tableData.getFloatField("speed", -1);
|
||||||
|
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
||||||
|
entry.playerHeight = tableData.getFloatField("playerHeight");
|
||||||
|
entry.playerRadius = tableData.getFloatField("playerRadius");
|
||||||
|
entry.pcShapeType = tableData.getIntField("pcShapeType");
|
||||||
|
entry.collisionGroup = tableData.getIntField("collisionGroup");
|
||||||
|
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
||||||
|
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
||||||
|
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
||||||
|
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
||||||
|
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
||||||
|
|
||||||
|
m_entries.insert(std::make_pair(entry.id, entry));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
|
||||||
|
auto itr = m_entries.find(componentID);
|
||||||
|
return itr != m_entries.end() ? &itr->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -23,12 +23,11 @@ struct CDPhysicsComponent {
|
|||||||
|
|
||||||
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
class CDPhysicsComponentTable : public CDTable<CDPhysicsComponentTable> {
|
||||||
public:
|
public:
|
||||||
CDPhysicsComponentTable();
|
void LoadValuesFromDatabase();
|
||||||
~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;
|
||||||
};
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user