Merge remote-tracking branch 'origin/main' into grim-lu

This commit is contained in:
wincent 2023-10-07 14:22:23 +02:00
commit 2097dbfff1
407 changed files with 6059 additions and 3708 deletions

View File

@ -97,15 +97,56 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy resource files on first build # Copy resource files on first build
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf") set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
foreach(resource_file ${RESOURCE_FILES}) message(STATUS "Checking resource file integrity")
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file}) foreach (resource_file ${RESOURCE_FILES})
set(file_size 0)
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
endif()
if (${file_size} EQUAL 0)
configure_file( configure_file(
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file} ${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
COPYONLY COPYONLY
) )
message("Moved ${resource_file} to project binary directory") message(STATUS "Moved " ${resource_file} " to project binary directory")
elseif (resource_file MATCHES ".ini")
message(STATUS "Checking " ${resource_file} " for missing config options")
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
set(parsed_current_file_contents "")
# Remove comment lines so they do not interfere with the variable parsing
foreach (line ${current_file_contents})
string(FIND ${line} "#" is_comment)
if (NOT ${is_comment} EQUAL 0)
string(APPEND parsed_current_file_contents ${line})
endif()
endforeach()
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
set(line_to_add "")
foreach (line ${depot_file_contents})
string(FIND ${line} "#" is_comment)
if (NOT ${is_comment} EQUAL 0)
string(REPLACE "=" ";" line_split ${line})
list(GET line_split 0 variable_name)
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
set(line_to_add ${line_to_add} ${line})
foreach (line_to_append ${line_to_add})
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
endforeach()
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
endif()
set(line_to_add "")
else()
set(line_to_add ${line_to_add} ${line})
endif()
endforeach()
endif() endif()
endforeach() endforeach()
message(STATUS "Resource file integrity check complete")
# Copy navmesh data on first build and extract it # Copy navmesh data on first build and extract it
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/) if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)

View File

@ -1,12 +1,8 @@
PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MAJOR=1
PROJECT_VERSION_MINOR=0 PROJECT_VERSION_MINOR=1
PROJECT_VERSION_PATCH=4 PROJECT_VERSION_PATCH=1
# LICENSE # LICENSE
LICENSE=AGPL-3.0 LICENSE=AGPL-3.0
# The network version.
# 171023 - Darkflame Universe client
# 171022 - Unmodded client
NET_VERSION=171022
# Debugging # Debugging
# Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs. # Set __dynamic to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
__dynamic=1 __dynamic=1
@ -22,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

View File

@ -179,7 +179,7 @@ If you would like to build the server faster, append `-j<number>` where number i
### Notes ### Notes
Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building: Depending on your operating system, you may need to adjust some pre-processor defines in [CMakeVariables.txt](./CMakeVariables.txt) before building:
* If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory. * If you are on MacOS, ensure OPENSSL_ROOT_DIR is pointing to the openssl root directory.
* If you are using a Darkflame Universe client, ensure NET_VERSION is changed to 171023. * If you are using a Darkflame Universe client, ensure `client_net_version` in `build/sharedconfig.ini` is changed to 171023.
## Configuring your server ## Configuring your server
This server has a few steps that need to be taken to configure the server for your use case. This server has a few steps that need to be taken to configure the server for your use case.
@ -338,7 +338,7 @@ This is a Work in Progress, but below are some quick links to documentaion for s
## Former Contributors ## Former Contributors
* TheMachine * TheMachine
* Matthew * Matthew
* [Raine](https://github.com/Rainebannister) * [Raine](https://github.com/uwainium)
* Bricknave * Bricknave
## Special Thanks ## Special Thanks

View File

@ -29,6 +29,7 @@ namespace Game {
dServer* server = nullptr; dServer* server = nullptr;
dConfig* config = nullptr; dConfig* config = nullptr;
bool shouldShutdown = false; bool shouldShutdown = false;
std::mt19937 randomEngine;
} }
dLogger* SetupLogger(); dLogger* SetupLogger();
@ -83,6 +84,8 @@ int main(int argc, char** argv) {
delete res; delete res;
delete stmt; delete stmt;
Game::randomEngine = std::mt19937(time(0));
//It's safe to pass 'localhost' here, as the IP is only used as the external IP. //It's safe to pass 'localhost' here, as the IP is only used as the external IP.
uint32_t maxClients = 50; uint32_t maxClients = 50;
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default. uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.

View File

@ -3,6 +3,7 @@
#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"
@ -75,11 +76,11 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Now, we need to send the friendlist to the server they came from: //Now, we need to send the friendlist to the server they came from:
CBITSTREAM; CBITSTREAM;
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)friends.size());
@ -412,21 +413,21 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
const auto otherName = std::string(otherMember->playerName.c_str()); const auto otherName = std::string(otherMember->playerName.c_str());
CBITSTREAM; CBITSTREAM;
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,7 +435,7 @@ 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);
@ -451,21 +452,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 +475,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;
@ -709,13 +710,13 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
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 +725,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 +752,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 +777,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 +794,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 +823,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 +849,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 +883,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 +922,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 +938,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 +963,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;

View File

@ -33,6 +33,7 @@ namespace Game {
dChatFilter* chatFilter = nullptr; dChatFilter* chatFilter = nullptr;
AssetManager* assetManager = nullptr; AssetManager* assetManager = nullptr;
bool shouldShutdown = false; bool shouldShutdown = false;
std::mt19937 randomEngine;
} }
@ -115,6 +116,8 @@ int main(int argc, char** argv) {
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf")))); Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", bool(std::stoi(Game::config->GetValue("dont_generate_dcf"))));
Game::randomEngine = std::mt19937(time(0));
//Run it until server gets a kill message from Master: //Run it until server gets a kill message from Master:
auto t = std::chrono::high_resolution_clock::now(); auto t = std::chrono::high_resolution_clock::now();
Packet* packet = nullptr; Packet* packet = nullptr;

View File

@ -6,10 +6,11 @@
#include "dLogger.h" #include "dLogger.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"
PlayerContainer::PlayerContainer() { PlayerContainer::PlayerContainer() {
} }
@ -146,7 +147,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);
@ -207,6 +208,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){
Game::logger->Log("PlayerContainer", "Tried to add player to team that already had 4 players");
auto* player = GetPlayerData(playerID);
if (!player) return;
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!");
return;
}
const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID); const auto index = std::find(team->memberIDs.begin(), team->memberIDs.end(), playerID);
if (index != team->memberIDs.end()) return; if (index != team->memberIDs.end()) return;
@ -345,7 +354,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);

View File

@ -10,6 +10,8 @@ class dConfig;
class RakPeerInterface; class RakPeerInterface;
class AssetManager; class AssetManager;
struct SystemAddress; struct SystemAddress;
class EntityManager;
class dZoneManager;
namespace Game { namespace Game {
extern dLogger* logger; extern dLogger* logger;
@ -22,4 +24,6 @@ namespace Game {
extern AssetManager* assetManager; extern AssetManager* assetManager;
extern SystemAddress chatSysAddr; extern SystemAddress chatSysAddr;
extern bool shouldShutdown; extern bool shouldShutdown;
extern EntityManager* entityManager;
extern dZoneManager* zoneManager;
} }

View File

@ -111,29 +111,6 @@ namespace GeneralUtils {
*/ */
bool CheckBit(int64_t value, uint32_t index); bool CheckBit(int64_t value, uint32_t index);
// MARK: Random Number Generation
//! Generates a random number
/*!
\param min The minimum the generate from
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
} else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
}
return T();
}
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to); bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
std::u16string ReadWString(RakNet::BitStream* inStream); std::u16string ReadWString(RakNet::BitStream* inStream);
@ -223,4 +200,42 @@ namespace GeneralUtils {
std::hash<T> h; std::hash<T> h;
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
} }
// MARK: Random Number Generation
//! Generates a random number
/*!
\param min The minimum the generate from
\param max The maximum to generate to
*/
template <typename T>
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
std::uniform_int_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
} else if (std::is_floating_point_v<T>) {
std::uniform_real_distribution<T> distribution(min, max);
return distribution(Game::randomEngine);
}
return T();
}
// on Windows we need to undef these or else they conflict with our numeric limits calls
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
#ifdef _WIN32
#undef min
#undef max
#endif
template <typename T>
inline T GenerateRandomNumber() {
// Make sure it is a numeric type
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
}
} }

View File

@ -129,10 +129,19 @@ NiPoint3 NiPoint3::operator+(const NiPoint3& point) const {
} }
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 NiPoint3::operator+=(const NiPoint3& point) const { NiPoint3& NiPoint3::operator+=(const NiPoint3& point) {
return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z); this->x += point.x;
this->y += point.y;
this->z += point.z;
return *this;
} }
NiPoint3& NiPoint3::operator*=(const float scalar) {
this->x *= scalar;
this->y *= scalar;
this->z *= scalar;
return *this;
}
//! Operator for subtraction of vectors //! Operator for subtraction of vectors
NiPoint3 NiPoint3::operator-(const NiPoint3& point) const { NiPoint3 NiPoint3::operator-(const NiPoint3& point) const {

View File

@ -136,7 +136,9 @@ public:
NiPoint3 operator+(const NiPoint3& point) const; NiPoint3 operator+(const NiPoint3& point) const;
//! Operator for addition of vectors //! Operator for addition of vectors
NiPoint3 operator+=(const NiPoint3& point) const; 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;

View File

@ -42,7 +42,7 @@ struct AssetMemoryBuffer : std::streambuf {
} }
void close() { void close() {
delete m_Base; free(m_Base);
} }
}; };

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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

View File

@ -38,43 +38,53 @@
#include "CDFeatureGatingTable.h" #include "CDFeatureGatingTable.h"
#include "CDRailActivatorComponent.h" #include "CDRailActivatorComponent.h"
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
// A vanilla CDClient takes about 46MB of memory + the regular world data.
// #define CDCLIENT_CACHE_ALL
#ifdef CDCLIENT_CACHE_ALL
#define CDCLIENT_DONT_CACHE_TABLE(x) x
#else
#define CDCLIENT_DONT_CACHE_TABLE(x)
#endif
CDClientManager::CDClientManager() { CDClientManager::CDClientManager() {
CDActivityRewardsTable::Instance(); CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
CDAnimationsTable::Instance(); CDActivitiesTable::Instance().LoadValuesFromDatabase();
CDBehaviorParameterTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDAnimationsTable::Instance().LoadValuesFromDatabase());
CDBehaviorTemplateTable::Instance(); CDBehaviorParameterTable::Instance().LoadValuesFromDatabase();
CDComponentsRegistryTable::Instance(); CDBehaviorTemplateTable::Instance().LoadValuesFromDatabase();
CDCurrencyTableTable::Instance(); CDBrickIDTableTable::Instance().LoadValuesFromDatabase();
CDDestructibleComponentTable::Instance(); CDComponentsRegistryTable::Instance().LoadValuesFromDatabase();
CDEmoteTableTable::Instance(); CDCurrencyTableTable::Instance().LoadValuesFromDatabase();
CDInventoryComponentTable::Instance(); CDDestructibleComponentTable::Instance().LoadValuesFromDatabase();
CDItemComponentTable::Instance(); CDEmoteTableTable::Instance().LoadValuesFromDatabase();
CDItemSetsTable::Instance(); CDFeatureGatingTable::Instance().LoadValuesFromDatabase();
CDItemSetSkillsTable::Instance(); CDInventoryComponentTable::Instance().LoadValuesFromDatabase();
CDLevelProgressionLookupTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDItemComponentTable::Instance().LoadValuesFromDatabase());
CDLootMatrixTable::Instance(); CDItemSetSkillsTable::Instance().LoadValuesFromDatabase();
CDLootTableTable::Instance(); CDItemSetsTable::Instance().LoadValuesFromDatabase();
CDMissionNPCComponentTable::Instance(); CDLevelProgressionLookupTable::Instance().LoadValuesFromDatabase();
CDMissionTasksTable::Instance(); CDLootMatrixTable::Instance().LoadValuesFromDatabase();
CDMissionsTable::Instance(); CDLootTableTable::Instance().LoadValuesFromDatabase();
CDObjectSkillsTable::Instance(); CDMissionEmailTable::Instance().LoadValuesFromDatabase();
CDObjectsTable::Instance(); CDMissionNPCComponentTable::Instance().LoadValuesFromDatabase();
CDPhysicsComponentTable::Instance(); CDMissionTasksTable::Instance().LoadValuesFromDatabase();
CDRebuildComponentTable::Instance(); CDMissionsTable::Instance().LoadValuesFromDatabase();
CDScriptComponentTable::Instance(); CDMovementAIComponentTable::Instance().LoadValuesFromDatabase();
CDSkillBehaviorTable::Instance(); CDObjectSkillsTable::Instance().LoadValuesFromDatabase();
CDZoneTableTable::Instance(); CDCLIENT_DONT_CACHE_TABLE(CDObjectsTable::Instance().LoadValuesFromDatabase());
CDVendorComponentTable::Instance(); CDPhysicsComponentTable::Instance().LoadValuesFromDatabase();
CDActivitiesTable::Instance(); CDPackageComponentTable::Instance().LoadValuesFromDatabase();
CDPackageComponentTable::Instance(); CDProximityMonitorComponentTable::Instance().LoadValuesFromDatabase();
CDProximityMonitorComponentTable::Instance(); CDPropertyEntranceComponentTable::Instance().LoadValuesFromDatabase();
CDMovementAIComponentTable::Instance(); CDPropertyTemplateTable::Instance().LoadValuesFromDatabase();
CDBrickIDTableTable::Instance(); CDRailActivatorComponentTable::Instance().LoadValuesFromDatabase();
CDRarityTableTable::Instance(); CDRarityTableTable::Instance().LoadValuesFromDatabase();
CDMissionEmailTable::Instance(); CDRebuildComponentTable::Instance().LoadValuesFromDatabase();
CDRewardsTable::Instance(); CDRewardsTable::Instance().LoadValuesFromDatabase();
CDPropertyEntranceComponentTable::Instance(); CDScriptComponentTable::Instance().LoadValuesFromDatabase();
CDPropertyTemplateTable::Instance(); CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
CDFeatureGatingTable::Instance(); CDVendorComponentTable::Instance().LoadValuesFromDatabase();
CDRailActivatorComponentTable::Instance(); CDZoneTableTable::Instance().LoadValuesFromDatabase();
} }

View File

@ -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;
}

View File

@ -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; }
}; };

View File

@ -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;
}

View File

@ -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;
}; };

View File

@ -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.

View File

@ -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

View File

@ -1,26 +1,30 @@
#include "CDBehaviorParameterTable.h" #include "CDBehaviorParameterTable.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
CDBehaviorParameterTable::CDBehaviorParameterTable(void) { uint64_t GetKey(const uint32_t behaviorID, const uint32_t parameterID) {
uint64_t key = behaviorID;
key <<= 31U;
key |= parameterID;
return key;
}
void CDBehaviorParameterTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM BehaviorParameter");
uint32_t uniqueParameterId = 0;
uint64_t hash = 0;
while (!tableData.eof()) { while (!tableData.eof()) {
CDBehaviorParameter entry; uint32_t behaviorID = tableData.getIntField("behaviorID", -1);
entry.behaviorID = tableData.getIntField("behaviorID", -1);
auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", "")); auto candidateStringToAdd = std::string(tableData.getStringField("parameterID", ""));
auto parameter = m_ParametersList.find(candidateStringToAdd); auto parameter = m_ParametersList.find(candidateStringToAdd);
uint32_t parameterId;
if (parameter != m_ParametersList.end()) { if (parameter != m_ParametersList.end()) {
entry.parameterID = parameter; parameterId = parameter->second;
} else { } else {
entry.parameterID = m_ParametersList.insert(std::make_pair(candidateStringToAdd, uniqueParameterId)).first; parameterId = m_ParametersList.insert(std::make_pair(candidateStringToAdd, m_ParametersList.size())).first->second;
uniqueParameterId++;
} }
hash = entry.behaviorID; uint64_t hash = GetKey(behaviorID, parameterId);
hash = (hash << 31U) | entry.parameterID->second; float value = tableData.getFloatField("value", -1.0f);
entry.value = tableData.getFloatField("value", -1.0f);
m_Entries.insert(std::make_pair(hash, entry)); m_Entries.insert(std::make_pair(hash, value));
tableData.nextRow(); tableData.nextRow();
} }
@ -30,27 +34,22 @@ CDBehaviorParameterTable::CDBehaviorParameterTable(void) {
float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) { float CDBehaviorParameterTable::GetValue(const uint32_t behaviorID, const std::string& name, const float defaultValue) {
auto parameterID = this->m_ParametersList.find(name); auto parameterID = this->m_ParametersList.find(name);
if (parameterID == this->m_ParametersList.end()) return defaultValue; if (parameterID == this->m_ParametersList.end()) return defaultValue;
auto hash = GetKey(behaviorID, parameterID->second);
uint64_t hash = behaviorID;
hash = (hash << 31U) | parameterID->second;
// Search for specific parameter // Search for specific parameter
const auto& it = m_Entries.find(hash); auto it = m_Entries.find(hash);
return it != m_Entries.end() ? it->second.value : defaultValue; return it != m_Entries.end() ? it->second : defaultValue;
} }
std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) { std::map<std::string, float> CDBehaviorParameterTable::GetParametersByBehaviorID(uint32_t behaviorID) {
uint64_t hashBase = behaviorID; uint64_t hashBase = behaviorID;
std::map<std::string, float> returnInfo; std::map<std::string, float> returnInfo;
uint64_t hash; for (auto& [parameterString, parameterId] : m_ParametersList) {
for (auto& parameterCandidate : m_ParametersList) { uint64_t hash = GetKey(hashBase, parameterId);
hash = (hashBase << 31U) | parameterCandidate.second;
auto infoCandidate = m_Entries.find(hash); auto infoCandidate = m_Entries.find(hash);
if (infoCandidate != m_Entries.end()) { if (infoCandidate != m_Entries.end()) {
returnInfo.insert(std::make_pair(infoCandidate->second.parameterID->first, infoCandidate->second.value)); returnInfo.insert(std::make_pair(parameterString, infoCandidate->second));
} }
} }
return returnInfo; return returnInfo;
} }

View File

@ -5,18 +5,15 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
struct CDBehaviorParameter {
unsigned int behaviorID; //!< The Behavior ID
std::unordered_map<std::string, uint32_t>::iterator parameterID; //!< The Parameter ID
float value; //!< The value of the behavior template
};
class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> { class CDBehaviorParameterTable : public CDTable<CDBehaviorParameterTable> {
private: private:
std::unordered_map<uint64_t, CDBehaviorParameter> m_Entries; typedef uint64_t BehaviorParameterHash;
typedef float BehaviorParameterValue;
std::unordered_map<BehaviorParameterHash, BehaviorParameterValue> m_Entries;
std::unordered_map<std::string, uint32_t> m_ParametersList; std::unordered_map<std::string, uint32_t> m_ParametersList;
public: public:
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);
std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID); std::map<std::string, float> GetParametersByBehaviorID(uint32_t behaviorID);

View File

@ -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;
} }
} }

View File

@ -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);
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -1,27 +1,37 @@
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#define CDCLIENT_CACHE_ALL void CDComponentsRegistryTable::LoadValuesFromDatabase() {
CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
#ifdef CDCLIENT_CACHE_ALL
// First, get the size of the table
unsigned int size = 0;
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM ComponentsRegistry");
while (!tableSize.eof()) {
size = tableSize.getIntField(0, 0);
tableSize.nextRow();
}
tableSize.finalize();
// Reserve the size
//this->entries.reserve(size);
// Now get the data // Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ComponentsRegistry");
while (!tableData.eof()) {
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()) { while (!tableData.eof()) {
CDComponentsRegistry entry; CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
@ -33,61 +43,10 @@ CDComponentsRegistryTable::CDComponentsRegistryTable(void) {
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); mappedEntries.insert_or_assign(id, 0);
#endif
} auto iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue) { return iter == this->mappedEntries.end() ? defaultValue : iter->second;
const auto& iter = this->mappedEntries.find(((uint64_t)componentType) << 32 | ((uint64_t)id));
if (iter == this->mappedEntries.end()) {
return defaultValue;
}
return iter->second;
#ifndef CDCLIENT_CACHE_ALL
// Now get the data
std::stringstream query;
query << "SELECT * FROM ComponentsRegistry WHERE id = " << std::to_string(id);
auto tableData = CDClientDatabase::ExecuteQuery(query.str());
while (!tableData.eof()) {
CDComponentsRegistry entry;
entry.id = tableData.getIntField("id", -1);
entry.component_type = tableData.getIntField("component_type", -1);
entry.component_id = tableData.getIntField("component_id", -1);
//this->entries.push_back(entry);
//Darwin's stuff:
const auto& it = this->mappedEntries.find(entry.id);
if (it != mappedEntries.end()) {
const auto& iter = it->second.find(entry.component_type);
if (iter == it->second.end()) {
it->second.insert(std::make_pair(entry.component_type, entry.component_id));
}
} else {
std::map<unsigned int, unsigned int> map;
map.insert(std::make_pair(entry.component_type, entry.component_id));
this->mappedEntries.insert(std::make_pair(entry.id, map));
}
tableData.nextRow();
}
tableData.finalize();
const auto& it2 = this->mappedEntries.find(id);
if (it2 != mappedEntries.end()) {
const auto& iter = it2->second.find(componentType);
if (iter != it2->second.end()) {
return iter->second;
}
}
return defaultValue;
#endif
} }

View File

@ -13,9 +13,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);
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -1,40 +1,26 @@
#include "CDEmoteTable.h" #include "CDEmoteTable.h"
//! Constructor void CDEmoteTableTable::LoadValuesFromDatabase() {
CDEmoteTableTable::CDEmoteTableTable(void) {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Emotes");
while (!tableData.eof()) { while (!tableData.eof()) {
CDEmoteTable* entry = new CDEmoteTable(); CDEmoteTable entry;
entry->ID = tableData.getIntField("id", -1); entry.ID = tableData.getIntField("id", -1);
entry->animationName = tableData.getStringField("animationName", ""); entry.animationName = tableData.getStringField("animationName", "");
entry->iconFilename = tableData.getStringField("iconFilename", ""); entry.iconFilename = tableData.getStringField("iconFilename", "");
entry->channel = tableData.getIntField("channel", -1); entry.channel = tableData.getIntField("channel", -1);
entry->locked = tableData.getIntField("locked", -1) != 0; entry.locked = tableData.getIntField("locked", -1) != 0;
entry->localize = tableData.getIntField("localize", -1) != 0; entry.localize = tableData.getIntField("localize", -1) != 0;
entry->locState = tableData.getIntField("locStatus", -1); entry.locState = tableData.getIntField("locStatus", -1);
entry->gateVersion = tableData.getStringField("gate_version", ""); entry.gateVersion = tableData.getStringField("gate_version", "");
entries.insert(std::make_pair(entry->ID, entry)); entries.insert(std::make_pair(entry.ID, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
//! Destructor
CDEmoteTableTable::~CDEmoteTableTable(void) {
for (auto e : entries) {
if (e.second) delete e.second;
}
entries.clear();
}
CDEmoteTable* CDEmoteTableTable::GetEmote(int id) { CDEmoteTable* CDEmoteTableTable::GetEmote(int id) {
for (auto e : entries) { auto itr = entries.find(id);
if (e.first == id) return e.second; return itr != entries.end() ? &itr->second : nullptr;
}
return nullptr;
} }

View File

@ -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);
}; };

View File

@ -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;
@ -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;
} }

View File

@ -16,11 +16,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 std::string& feature) const;
std::vector<CDFeatureGating> GetEntries(void) const; const std::vector<CDFeatureGating>& GetEntries(void) const;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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);
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -1,7 +1,6 @@
#include "CDLootMatrixTable.h" #include "CDLootMatrixTable.h"
//! Constructor void CDLootMatrixTable::LoadValuesFromDatabase() {
CDLootMatrixTable::CDLootMatrixTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@ -47,7 +46,7 @@ std::vector<CDLootMatrix> CDLootMatrixTable::Query(std::function<bool(CDLootMatr
return data; return data;
} }
const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries(void) const { const std::vector<CDLootMatrix>& CDLootMatrixTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@ -20,10 +20,10 @@ private:
std::vector<CDLootMatrix> entries; std::vector<CDLootMatrix> entries;
public: public:
CDLootMatrixTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate); std::vector<CDLootMatrix> Query(std::function<bool(CDLootMatrix)> predicate);
const std::vector<CDLootMatrix>& GetEntries(void) const; const std::vector<CDLootMatrix>& GetEntries() const;
}; };

View File

@ -1,7 +1,6 @@
#include "CDLootTableTable.h" #include "CDLootTableTable.h"
//! Constructor void CDLootTableTable::LoadValuesFromDatabase() {
CDLootTableTable::CDLootTableTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@ -46,7 +45,7 @@ std::vector<CDLootTable> CDLootTableTable::Query(std::function<bool(CDLootTable)
} }
//! Gets all the entries in the table //! Gets all the entries in the table
const std::vector<CDLootTable>& CDLootTableTable::GetEntries(void) const { const std::vector<CDLootTable>& CDLootTableTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@ -16,10 +16,10 @@ private:
std::vector<CDLootTable> entries; std::vector<CDLootTable> 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); std::vector<CDLootTable> Query(std::function<bool(CDLootTable)> predicate);
const std::vector<CDLootTable>& GetEntries(void) const; const std::vector<CDLootTable>& GetEntries() const;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -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;
} }

View File

@ -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);
}; };

View File

@ -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;
} }

View File

@ -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;
}; };

View File

@ -1,46 +1,35 @@
#include "CDPhysicsComponentTable.h" #include "CDPhysicsComponentTable.h"
CDPhysicsComponentTable::CDPhysicsComponentTable(void) { void CDPhysicsComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
while (!tableData.eof()) { while (!tableData.eof()) {
CDPhysicsComponent* entry = new CDPhysicsComponent(); CDPhysicsComponent entry;
entry->id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry->bStatic = tableData.getIntField("static", -1) != 0; entry.bStatic = tableData.getIntField("static", -1) != 0;
entry->physicsAsset = tableData.getStringField("physics_asset", ""); entry.physicsAsset = tableData.getStringField("physics_asset", "");
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0); UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0); UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
entry->speed = tableData.getFloatField("speed", -1); entry.speed = tableData.getFloatField("speed", -1);
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1)); UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
entry->playerHeight = tableData.getFloatField("playerHeight"); entry.playerHeight = tableData.getFloatField("playerHeight");
entry->playerRadius = tableData.getFloatField("playerRadius"); entry.playerRadius = tableData.getFloatField("playerRadius");
entry->pcShapeType = tableData.getIntField("pcShapeType"); entry.pcShapeType = tableData.getIntField("pcShapeType");
entry->collisionGroup = tableData.getIntField("collisionGroup"); entry.collisionGroup = tableData.getIntField("collisionGroup");
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed")); UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset")); UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed")); UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
UNUSED(entry->friction = tableData.getFloatField("friction")); UNUSED(entry->friction = tableData.getFloatField("friction"));
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset")); UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
m_entries.insert(std::make_pair(entry->id, entry)); m_entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
CDPhysicsComponentTable::~CDPhysicsComponentTable() {
for (auto e : m_entries) {
if (e.second) delete e.second;
}
m_entries.clear();
}
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) { CDPhysicsComponent* CDPhysicsComponentTable::GetByID(unsigned int componentID) {
for (auto e : m_entries) { auto itr = m_entries.find(componentID);
if (e.first == componentID) return e.second; return itr != m_entries.end() ? &itr->second : nullptr;
}
return nullptr;
} }

View File

@ -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;
}; };

View File

@ -1,7 +1,6 @@
#include "CDPropertyEntranceComponentTable.h" #include "CDPropertyEntranceComponentTable.h"
CDPropertyEntranceComponentTable::CDPropertyEntranceComponentTable() { void CDPropertyEntranceComponentTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
size_t size = 0; size_t size = 0;

View File

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

View File

@ -1,6 +1,6 @@
#include "CDPropertyTemplateTable.h" #include "CDPropertyTemplateTable.h"
CDPropertyTemplateTable::CDPropertyTemplateTable() { void CDPropertyTemplateTable::LoadValuesFromDatabase() {
// First, get the size of the table // First, get the size of the table
size_t size = 0; size_t size = 0;

View File

@ -10,7 +10,7 @@ struct CDPropertyTemplate {
class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> { class CDPropertyTemplateTable : public CDTable<CDPropertyTemplateTable> {
public: public:
CDPropertyTemplateTable(); void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PropertyTemplate"; }; static const std::string GetTableName() { return "PropertyTemplate"; };
CDPropertyTemplate GetByMapID(uint32_t mapID); CDPropertyTemplate GetByMapID(uint32_t mapID);

View File

@ -1,7 +1,6 @@
#include "CDProximityMonitorComponentTable.h" #include "CDProximityMonitorComponentTable.h"
//! Constructor void CDProximityMonitorComponentTable::LoadValuesFromDatabase() {
CDProximityMonitorComponentTable::CDProximityMonitorComponentTable(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 @@ CDProximityMonitorComponentTable::CDProximityMonitorComponentTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) { std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query(std::function<bool(CDProximityMonitorComponent)> predicate) {
std::vector<CDProximityMonitorComponent> data = cpplinq::from(this->entries) std::vector<CDProximityMonitorComponent> data = cpplinq::from(this->entries)
@ -43,8 +41,7 @@ std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::Query
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDProximityMonitorComponent>& CDProximityMonitorComponentTable::GetEntries() const {
std::vector<CDProximityMonitorComponent> CDProximityMonitorComponentTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

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

View File

@ -1,7 +1,7 @@
#include "CDRailActivatorComponent.h" #include "CDRailActivatorComponent.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
CDRailActivatorComponentTable::CDRailActivatorComponentTable() { void CDRailActivatorComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RailActivatorComponent;"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM RailActivatorComponent;");
while (!tableData.eof()) { while (!tableData.eof()) {
CDRailActivatorComponent entry; CDRailActivatorComponent entry;
@ -52,7 +52,7 @@ CDRailActivatorComponent CDRailActivatorComponentTable::GetEntryByID(int32_t id)
return {}; return {};
} }
std::vector<CDRailActivatorComponent> CDRailActivatorComponentTable::GetEntries() const { const std::vector<CDRailActivatorComponent>& CDRailActivatorComponentTable::GetEntries() const {
return m_Entries; return m_Entries;
} }

View File

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

View File

@ -1,7 +1,6 @@
#include "CDRarityTableTable.h" #include "CDRarityTableTable.h"
//! Constructor void CDRarityTableTable::LoadValuesFromDatabase() {
CDRarityTableTable::CDRarityTableTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@ -44,7 +43,7 @@ std::vector<CDRarityTable> CDRarityTableTable::Query(std::function<bool(CDRarity
} }
//! Gets all the entries in the table //! Gets all the entries in the table
const std::vector<CDRarityTable>& CDRarityTableTable::GetEntries(void) const { const std::vector<CDRarityTable>& CDRarityTableTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@ -31,7 +31,7 @@ private:
std::vector<CDRarityTable> entries; std::vector<CDRarityTable> entries;
public: public:
CDRarityTableTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDRarityTable> Query(std::function<bool(CDRarityTable)> predicate); std::vector<CDRarityTable> Query(std::function<bool(CDRarityTable)> predicate);

View File

@ -1,7 +1,6 @@
#include "CDRebuildComponentTable.h" #include "CDRebuildComponentTable.h"
//! Constructor void CDRebuildComponentTable::LoadValuesFromDatabase() {
CDRebuildComponentTable::CDRebuildComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@ -39,7 +38,6 @@ CDRebuildComponentTable::CDRebuildComponentTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<bool(CDRebuildComponent)> predicate) { std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<bool(CDRebuildComponent)> predicate) {
std::vector<CDRebuildComponent> data = cpplinq::from(this->entries) std::vector<CDRebuildComponent> data = cpplinq::from(this->entries)
@ -49,8 +47,7 @@ std::vector<CDRebuildComponent> CDRebuildComponentTable::Query(std::function<boo
return data; return data;
} }
//! Gets all the entries in the table const std::vector<CDRebuildComponent>& CDRebuildComponentTable::GetEntries() const {
std::vector<CDRebuildComponent> CDRebuildComponentTable::GetEntries(void) const {
return this->entries; return this->entries;
} }

View File

@ -21,10 +21,10 @@ private:
std::vector<CDRebuildComponent> entries; std::vector<CDRebuildComponent> entries;
public: public:
CDRebuildComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDRebuildComponent> Query(std::function<bool(CDRebuildComponent)> predicate); std::vector<CDRebuildComponent> Query(std::function<bool(CDRebuildComponent)> predicate);
std::vector<CDRebuildComponent> GetEntries() const; const std::vector<CDRebuildComponent>& GetEntries() const;
}; };

View File

@ -1,35 +1,27 @@
#include "CDRewardsTable.h" #include "CDRewardsTable.h"
CDRewardsTable::CDRewardsTable(void) { void CDRewardsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards"); auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Rewards");
while (!tableData.eof()) { while (!tableData.eof()) {
CDRewards* entry = new CDRewards(); CDRewards entry;
entry->id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry->levelID = tableData.getIntField("LevelID", -1); entry.levelID = tableData.getIntField("LevelID", -1);
entry->missionID = tableData.getIntField("MissionID", -1); entry.missionID = tableData.getIntField("MissionID", -1);
entry->rewardType = tableData.getIntField("RewardType", -1); entry.rewardType = tableData.getIntField("RewardType", -1);
entry->value = tableData.getIntField("value", -1); entry.value = tableData.getIntField("value", -1);
entry->count = tableData.getIntField("count", -1); entry.count = tableData.getIntField("count", -1);
m_entries.insert(std::make_pair(entry->id, entry)); m_entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow(); tableData.nextRow();
} }
tableData.finalize(); tableData.finalize();
} }
CDRewardsTable::~CDRewardsTable(void) { std::vector<CDRewards> CDRewardsTable::GetByLevelID(uint32_t levelID) {
for (auto e : m_entries) { std::vector<CDRewards> result{};
if (e.second) delete e.second;
}
m_entries.clear();
}
std::vector<CDRewards*> CDRewardsTable::GetByLevelID(uint32_t levelID) {
std::vector<CDRewards*> result{};
for (const auto& e : m_entries) { for (const auto& e : m_entries) {
if (e.second->levelID == levelID) result.push_back(e.second); if (e.second.levelID == levelID) result.push_back(e.second);
} }
return result; return result;

View File

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

View File

@ -1,7 +1,6 @@
#include "CDScriptComponentTable.h" #include "CDScriptComponentTable.h"
//! Constructor void CDScriptComponentTable::LoadValuesFromDatabase() {
CDScriptComponentTable::CDScriptComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;

View File

@ -15,7 +15,7 @@ private:
CDScriptComponent m_ToReturnWhenNoneFound; CDScriptComponent m_ToReturnWhenNoneFound;
public: public:
CDScriptComponentTable(); void LoadValuesFromDatabase();
// Gets an entry by scriptID // Gets an entry by scriptID
const CDScriptComponent& GetByID(unsigned int id); const CDScriptComponent& GetByID(unsigned int id);
}; };

View File

@ -1,8 +1,6 @@
#include "CDSkillBehaviorTable.h" #include "CDSkillBehaviorTable.h"
//#include "Logger.hpp"
//! Constructor void CDSkillBehaviorTable::LoadValuesFromDatabase() {
CDSkillBehaviorTable::CDSkillBehaviorTable(void) {
m_empty = CDSkillBehavior(); m_empty = CDSkillBehavior();
// First, get the size of the table // First, get the size of the table
@ -51,13 +49,6 @@ CDSkillBehaviorTable::CDSkillBehaviorTable(void) {
tableData.finalize(); tableData.finalize();
} }
//! Queries the table with a custom "where" clause
std::vector<CDSkillBehavior> CDSkillBehaviorTable::Query(std::function<bool(CDSkillBehavior)> predicate) {
std::vector<CDSkillBehavior> data; //So MSVC shuts up
return data;
}
//! Gets an entry by ID
const CDSkillBehavior& CDSkillBehaviorTable::GetSkillByID(unsigned int skillID) { const CDSkillBehavior& CDSkillBehaviorTable::GetSkillByID(unsigned int skillID) {
std::map<unsigned int, CDSkillBehavior>::iterator it = this->entries.find(skillID); std::map<unsigned int, CDSkillBehavior>::iterator it = this->entries.find(skillID);
if (it != this->entries.end()) { if (it != this->entries.end()) {

View File

@ -31,9 +31,7 @@ private:
CDSkillBehavior m_empty; CDSkillBehavior m_empty;
public: public:
CDSkillBehaviorTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause
std::vector<CDSkillBehavior> Query(std::function<bool(CDSkillBehavior)> predicate);
// Gets an entry by skillID // Gets an entry by skillID
const CDSkillBehavior& GetSkillByID(unsigned int skillID); const CDSkillBehavior& GetSkillByID(unsigned int skillID);

View File

@ -1,7 +1,6 @@
#include "CDVendorComponentTable.h" #include "CDVendorComponentTable.h"
//! Constructor void CDVendorComponentTable::LoadValuesFromDatabase() {
CDVendorComponentTable::CDVendorComponentTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;
@ -22,7 +21,7 @@ CDVendorComponentTable::CDVendorComponentTable(void) {
while (!tableData.eof()) { while (!tableData.eof()) {
CDVendorComponent entry; CDVendorComponent entry;
entry.id = tableData.getIntField("id", -1); entry.id = tableData.getIntField("id", -1);
entry.buyScalar = tableData.getFloatField("buyScalar", -1.0f); entry.buyScalar = tableData.getFloatField("buyScalar", 0.0f);
entry.sellScalar = tableData.getFloatField("sellScalar", -1.0f); entry.sellScalar = tableData.getFloatField("sellScalar", -1.0f);
entry.refreshTimeSeconds = tableData.getFloatField("refreshTimeSeconds", -1.0f); entry.refreshTimeSeconds = tableData.getFloatField("refreshTimeSeconds", -1.0f);
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1); entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
@ -45,7 +44,7 @@ std::vector<CDVendorComponent> CDVendorComponentTable::Query(std::function<bool(
} }
//! Gets all the entries in the table //! Gets all the entries in the table
std::vector<CDVendorComponent> CDVendorComponentTable::GetEntries(void) const { const std::vector<CDVendorComponent>& CDVendorComponentTable::GetEntries() const {
return this->entries; return this->entries;
} }

View File

@ -16,10 +16,10 @@ private:
std::vector<CDVendorComponent> entries; std::vector<CDVendorComponent> entries;
public: public:
CDVendorComponentTable(); void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause // Queries the table with a custom "where" clause
std::vector<CDVendorComponent> Query(std::function<bool(CDVendorComponent)> predicate); std::vector<CDVendorComponent> Query(std::function<bool(CDVendorComponent)> predicate);
std::vector<CDVendorComponent> GetEntries(void) const; const std::vector<CDVendorComponent>& GetEntries(void) const;
}; };

View File

@ -1,7 +1,6 @@
#include "CDZoneTableTable.h" #include "CDZoneTableTable.h"
//! Constructor void CDZoneTableTable::LoadValuesFromDatabase() {
CDZoneTableTable::CDZoneTableTable(void) {
// First, get the size of the table // First, get the size of the table
unsigned int size = 0; unsigned int size = 0;

View File

@ -38,7 +38,7 @@ private:
std::map<unsigned int, CDZoneTable> m_Entries; std::map<unsigned int, CDZoneTable> m_Entries;
public: public:
CDZoneTableTable(); void LoadValuesFromDatabase();
// Queries the table with a zoneID to find. // Queries the table with a zoneID to find.
const CDZoneTable* Query(unsigned int zoneID); const CDZoneTable* Query(unsigned int zoneID);

View File

@ -241,7 +241,7 @@ void Character::DoQuickXMLDataParse() {
//To try and fix the AG landing into: //To try and fix the AG landing into:
if (m_ZoneID == 1000 && Game::server->GetZoneID() == 1100) { if (m_ZoneID == 1000 && Game::server->GetZoneID() == 1100) {
//sneakily insert our position: //sneakily insert our position:
auto pos = dZoneManager::Instance()->GetZone()->GetSpawnPos(); auto pos = Game::zoneManager->GetZone()->GetSpawnPos();
character->SetAttribute("lzx", pos.x); character->SetAttribute("lzx", pos.x);
character->SetAttribute("lzy", pos.y); character->SetAttribute("lzy", pos.y);
character->SetAttribute("lzz", pos.z); character->SetAttribute("lzz", pos.z);
@ -290,13 +290,13 @@ void Character::DoQuickXMLDataParse() {
void Character::UnlockEmote(int emoteID) { void Character::UnlockEmote(int emoteID) {
m_UnlockedEmotes.push_back(emoteID); m_UnlockedEmotes.push_back(emoteID);
GameMessages::SendSetEmoteLockState(EntityManager::Instance()->GetEntity(m_ObjectID), false, emoteID); GameMessages::SendSetEmoteLockState(Game::entityManager->GetEntity(m_ObjectID), false, emoteID);
} }
void Character::SetBuildMode(bool buildMode) { void Character::SetBuildMode(bool buildMode) {
m_BuildMode = buildMode; m_BuildMode = buildMode;
auto* controller = dZoneManager::Instance()->GetZoneControlObject(); auto* controller = Game::zoneManager->GetZoneControlObject();
controller->OnFireEventServerSide(m_OurEntity, buildMode ? "OnBuildModeEnter" : "OnBuildModeLeave"); controller->OnFireEventServerSide(m_OurEntity, buildMode ? "OnBuildModeEnter" : "OnBuildModeLeave");
} }
@ -312,7 +312,7 @@ void Character::SaveXMLToDatabase() {
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel)); character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
character->SetAttribute("cc", m_Coins); character->SetAttribute("cc", m_Coins);
auto zoneInfo = dZoneManager::Instance()->GetZone()->GetZoneID(); auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID();
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone // lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) { if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
uint64_t lzidConcat = zoneInfo.GetCloneID(); uint64_t lzidConcat = zoneInfo.GetCloneID();
@ -418,13 +418,13 @@ void Character::WriteToDatabase() {
delete printer; delete printer;
} }
void Character::SetPlayerFlag(const int32_t flagId, const bool value) { void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
// If the flag is already set, we don't have to recalculate it // If the flag is already set, we don't have to recalculate it
if (GetPlayerFlag(flagId) == value) return; if (GetPlayerFlag(flagId) == value) return;
if (value) { if (value) {
// Update the mission component: // Update the mission component:
auto* player = EntityManager::Instance()->GetEntity(m_ObjectID); auto* player = Game::entityManager->GetEntity(m_ObjectID);
if (player != nullptr) { if (player != nullptr) {
auto* missionComponent = player->GetComponent<MissionComponent>(); auto* missionComponent = player->GetComponent<MissionComponent>();
@ -465,7 +465,7 @@ void Character::SetPlayerFlag(const int32_t flagId, const bool value) {
GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress()); GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress());
} }
bool Character::GetPlayerFlag(const int32_t flagId) const { bool Character::GetPlayerFlag(const uint32_t flagId) const {
// Calculate the index first // Calculate the index first
const auto flagIndex = uint32_t(std::floor(flagId / 64)); const auto flagIndex = uint32_t(std::floor(flagId / 64));
@ -602,7 +602,7 @@ void Character::SetCoins(int64_t newCoins, eLootSourceType lootSource) {
m_Coins = newCoins; m_Coins = newCoins;
GameMessages::SendSetCurrency(EntityManager::Instance()->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource); GameMessages::SendSetCurrency(Game::entityManager->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource);
} }
bool Character::HasBeenToWorld(LWOMAPID mapID) const { bool Character::HasBeenToWorld(LWOMAPID mapID) const {

View File

@ -415,14 +415,14 @@ public:
* @param flagId the ID of the flag to set * @param flagId the ID of the flag to set
* @param value the value to set for the flag * @param value the value to set for the flag
*/ */
void SetPlayerFlag(int32_t flagId, bool value); void SetPlayerFlag(uint32_t flagId, bool value);
/** /**
* Gets the value for a certain character flag * Gets the value for a certain character flag
* @param flagId the ID of the flag to get a value for * @param flagId the ID of the flag to get a value for
* @return the value of the flag given the ID (the default is false, obviously) * @return the value of the flag given the ID (the default is false, obviously)
*/ */
bool GetPlayerFlag(int32_t flagId) const; bool GetPlayerFlag(uint32_t flagId) const;
/** /**
* Notifies the character that they're now muted * Notifies the character that they're now muted

View File

@ -31,7 +31,7 @@
#include "Component.h" #include "Component.h"
#include "ControllablePhysicsComponent.h" #include "ControllablePhysicsComponent.h"
#include "RenderComponent.h" #include "RenderComponent.h"
#include "RocketLaunchLupComponent.h" #include "MultiZoneEntranceComponent.h"
#include "CharacterComponent.h" #include "CharacterComponent.h"
#include "DestroyableComponent.h" #include "DestroyableComponent.h"
#include "BuffComponent.h" #include "BuffComponent.h"
@ -52,6 +52,7 @@
#include "BuildBorderComponent.h" #include "BuildBorderComponent.h"
#include "MovementAIComponent.h" #include "MovementAIComponent.h"
#include "VendorComponent.h" #include "VendorComponent.h"
#include "DonationVendorComponent.h"
#include "RocketLaunchpadControlComponent.h" #include "RocketLaunchpadControlComponent.h"
#include "PropertyComponent.h" #include "PropertyComponent.h"
#include "BaseCombatAIComponent.h" #include "BaseCombatAIComponent.h"
@ -71,6 +72,7 @@
#include "ShootingGalleryComponent.h" #include "ShootingGalleryComponent.h"
#include "RailActivatorComponent.h" #include "RailActivatorComponent.h"
#include "LUPExhibitComponent.h" #include "LUPExhibitComponent.h"
#include "RacingSoundTriggerComponent.h"
#include "TriggerComponent.h" #include "TriggerComponent.h"
#include "eGameMasterLevel.h" #include "eGameMasterLevel.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
@ -264,17 +266,17 @@ void Entity::Initialize() {
NiQuaternion rot; NiQuaternion rot;
const auto& targetSceneName = m_Character->GetTargetScene(); const auto& targetSceneName = m_Character->GetTargetScene();
auto* targetScene = EntityManager::Instance()->GetSpawnPointEntity(targetSceneName); auto* targetScene = Game::entityManager->GetSpawnPointEntity(targetSceneName);
if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) { if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) {
pos = m_Character->GetRespawnPoint(mapID); pos = m_Character->GetRespawnPoint(mapID);
rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); rot = Game::zoneManager->GetZone()->GetSpawnRot();
} else if (targetScene != nullptr) { } else if (targetScene != nullptr) {
pos = targetScene->GetPosition(); pos = targetScene->GetPosition();
rot = targetScene->GetRotation(); rot = targetScene->GetRotation();
} else { } else {
pos = dZoneManager::Instance()->GetZone()->GetSpawnPos(); pos = Game::zoneManager->GetZone()->GetSpawnPos();
rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); rot = Game::zoneManager->GetZone()->GetSpawnRot();
} }
controllablePhysics->SetPosition(pos); controllablePhysics->SetPosition(pos);
@ -318,6 +320,9 @@ void Entity::Initialize() {
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
auto* comp = new SoundTriggerComponent(this); auto* comp = new SoundTriggerComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp)); m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp));
} else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) {
auto* comp = new RacingSoundTriggerComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::RACING_SOUND_TRIGGER, comp));
} }
//Also check for the collectible id: //Also check for the collectible id:
@ -468,9 +473,9 @@ void Entity::Initialize() {
m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp)); m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp));
} }
// if this component exists, then we initialize it. it's value is always 0 // if this component exists, then we initialize it. it's value is always 0
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH_LUP, -1) != -1) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
auto comp = new RocketLaunchLupComponent(this); auto comp = new MultiZoneEntranceComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH_LUP, comp)); m_Components.insert(std::make_pair(eReplicaComponentType::MULTI_ZONE_ENTRANCE, comp));
} }
/** /**
@ -527,7 +532,7 @@ void Entity::Initialize() {
// ZoneControl script // ZoneControl script
if (m_TemplateID == 2365) { if (m_TemplateID == 2365) {
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>(); CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
const auto zoneID = dZoneManager::Instance()->GetZoneID(); const auto zoneID = Game::zoneManager->GetZoneID();
const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID()); const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID());
if (zoneData != nullptr) { if (zoneData != nullptr) {
@ -600,6 +605,9 @@ void Entity::Initialize() {
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) { if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
VendorComponent* comp = new VendorComponent(this); VendorComponent* comp = new VendorComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp)); m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp));
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
DonationVendorComponent* comp = new DonationVendorComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::DONATION_VENDOR, comp));
} }
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
@ -713,7 +721,7 @@ void Entity::Initialize() {
} }
std::string pathName = GetVarAsString(u"attached_path"); std::string pathName = GetVarAsString(u"attached_path");
const Path* path = dZoneManager::Instance()->GetZone()->GetPath(pathName); const Path* path = Game::zoneManager->GetZone()->GetPath(pathName);
//Check to see if we have an attached path and add the appropiate component to handle it: //Check to see if we have an attached path and add the appropiate component to handle it:
if (path){ if (path){
@ -757,7 +765,7 @@ void Entity::Initialize() {
} }
}); });
if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) { if (!m_Character && Game::entityManager->GetGhostingEnabled()) {
// Don't ghost what is likely large scene elements // Don't ghost what is likely large scene elements
if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) { if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) {
goto no_ghosting; goto no_ghosting;
@ -1034,57 +1042,60 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
*/ */
bool destroyableSerialized = false; bool destroyableSerialized = false;
bool bIsInitialUpdate = false; bool bIsInitialUpdate = packetType == eReplicaPacketType::CONSTRUCTION;
if (packetType == eReplicaPacketType::CONSTRUCTION) bIsInitialUpdate = true;
unsigned int flags = 0;
PossessableComponent* possessableComponent; PossessableComponent* possessableComponent;
if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) { if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) {
possessableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); possessableComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ModuleAssemblyComponent* moduleAssemblyComponent; ModuleAssemblyComponent* moduleAssemblyComponent;
if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) { if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) {
moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate, flags); moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ControllablePhysicsComponent* controllablePhysicsComponent; ControllablePhysicsComponent* controllablePhysicsComponent;
if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) { if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) {
controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
SimplePhysicsComponent* simplePhysicsComponent; SimplePhysicsComponent* simplePhysicsComponent;
if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) { if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) {
simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics; RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics;
if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) { if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) {
rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate, flags); rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate);
} }
VehiclePhysicsComponent* vehiclePhysicsComponent; VehiclePhysicsComponent* vehiclePhysicsComponent;
if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) { if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) {
vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
PhantomPhysicsComponent* phantomPhysicsComponent; PhantomPhysicsComponent* phantomPhysicsComponent;
if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) { if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) {
phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
SoundTriggerComponent* soundTriggerComponent; SoundTriggerComponent* soundTriggerComponent;
if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) { if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) {
soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate);
}
RacingSoundTriggerComponent* racingSoundTriggerComponent;
if (TryGetComponent(eReplicaComponentType::RACING_SOUND_TRIGGER, racingSoundTriggerComponent)) {
racingSoundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
BuffComponent* buffComponent; BuffComponent* buffComponent;
if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) { if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) {
buffComponent->Serialize(outBitStream, bIsInitialUpdate, flags); buffComponent->Serialize(outBitStream, bIsInitialUpdate);
DestroyableComponent* destroyableComponent; DestroyableComponent* destroyableComponent;
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) { if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) {
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
destroyableSerialized = true; destroyableSerialized = true;
} }
@ -1092,7 +1103,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
if (HasComponent(eReplicaComponentType::COLLECTIBLE)) { if (HasComponent(eReplicaComponentType::COLLECTIBLE)) {
DestroyableComponent* destroyableComponent; DestroyableComponent* destroyableComponent;
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
destroyableSerialized = true; destroyableSerialized = true;
outBitStream->Write(m_CollectibleID); // Collectable component outBitStream->Write(m_CollectibleID); // Collectable component
@ -1100,7 +1111,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
PetComponent* petComponent; PetComponent* petComponent;
if (TryGetComponent(eReplicaComponentType::PET, petComponent)) { if (TryGetComponent(eReplicaComponentType::PET, petComponent)) {
petComponent->Serialize(outBitStream, bIsInitialUpdate, flags); petComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
CharacterComponent* characterComponent; CharacterComponent* characterComponent;
@ -1108,7 +1119,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
PossessorComponent* possessorComponent; PossessorComponent* possessorComponent;
if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) { if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) {
possessorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); possessorComponent->Serialize(outBitStream, bIsInitialUpdate);
} else { } else {
// Should never happen, but just to be safe // Should never happen, but just to be safe
outBitStream->Write0(); outBitStream->Write0();
@ -1116,7 +1127,7 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
LevelProgressionComponent* levelProgressionComponent; LevelProgressionComponent* levelProgressionComponent;
if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) { if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) {
levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate, flags); levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate);
} else { } else {
// Should never happen, but just to be safe // Should never happen, but just to be safe
outBitStream->Write0(); outBitStream->Write0();
@ -1124,13 +1135,13 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
PlayerForcedMovementComponent* playerForcedMovementComponent; PlayerForcedMovementComponent* playerForcedMovementComponent;
if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) { if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) {
playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate, flags); playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate);
} else { } else {
// Should never happen, but just to be safe // Should never happen, but just to be safe
outBitStream->Write0(); outBitStream->Write0();
} }
characterComponent->Serialize(outBitStream, bIsInitialUpdate, flags); characterComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
if (HasComponent(eReplicaComponentType::ITEM)) { if (HasComponent(eReplicaComponentType::ITEM)) {
@ -1139,88 +1150,93 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
InventoryComponent* inventoryComponent; InventoryComponent* inventoryComponent;
if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) { if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) {
inventoryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); inventoryComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ScriptComponent* scriptComponent; ScriptComponent* scriptComponent;
if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) { if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) {
scriptComponent->Serialize(outBitStream, bIsInitialUpdate, flags); scriptComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
SkillComponent* skillComponent; SkillComponent* skillComponent;
if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) { if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) {
skillComponent->Serialize(outBitStream, bIsInitialUpdate, flags); skillComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
BaseCombatAIComponent* baseCombatAiComponent; BaseCombatAIComponent* baseCombatAiComponent;
if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) { if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) {
baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate, flags); baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
RebuildComponent* rebuildComponent; RebuildComponent* rebuildComponent;
if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) { if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) {
DestroyableComponent* destroyableComponent; DestroyableComponent* destroyableComponent;
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
destroyableSerialized = true; destroyableSerialized = true;
rebuildComponent->Serialize(outBitStream, bIsInitialUpdate, flags); rebuildComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
MovingPlatformComponent* movingPlatformComponent; MovingPlatformComponent* movingPlatformComponent;
if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) { if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) {
movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate, flags); movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
SwitchComponent* switchComponent; SwitchComponent* switchComponent;
if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) { if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) {
switchComponent->Serialize(outBitStream, bIsInitialUpdate, flags); switchComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
VendorComponent* vendorComponent; VendorComponent* vendorComponent;
if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) { if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) {
vendorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); vendorComponent->Serialize(outBitStream, bIsInitialUpdate);
}
DonationVendorComponent* donationVendorComponent;
if (TryGetComponent(eReplicaComponentType::DONATION_VENDOR, donationVendorComponent)) {
donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
BouncerComponent* bouncerComponent; BouncerComponent* bouncerComponent;
if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) { if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) {
bouncerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); bouncerComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ScriptedActivityComponent* scriptedActivityComponent; ScriptedActivityComponent* scriptedActivityComponent;
if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) { if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) {
scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate, flags); scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ShootingGalleryComponent* shootingGalleryComponent; ShootingGalleryComponent* shootingGalleryComponent;
if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) { if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) {
shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
RacingControlComponent* racingControlComponent; RacingControlComponent* racingControlComponent;
if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) { if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) {
racingControlComponent->Serialize(outBitStream, bIsInitialUpdate, flags); racingControlComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
LUPExhibitComponent* lupExhibitComponent; LUPExhibitComponent* lupExhibitComponent;
if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) { if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) {
lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate, flags); lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
ModelComponent* modelComponent; ModelComponent* modelComponent;
if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) { if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) {
modelComponent->Serialize(outBitStream, bIsInitialUpdate, flags); modelComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
RenderComponent* renderComponent; RenderComponent* renderComponent;
if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) { if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) {
renderComponent->Serialize(outBitStream, bIsInitialUpdate, flags); renderComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
if (modelComponent) { if (modelComponent) {
DestroyableComponent* destroyableComponent; DestroyableComponent* destroyableComponent;
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
destroyableSerialized = true; destroyableSerialized = true;
} }
} }
@ -1235,10 +1251,6 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
outBitStream->Write0(); outBitStream->Write0();
} }
void Entity::ResetFlags() {
// Unused
}
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
//This function should only ever be called from within Character, meaning doc should always exist when this is called. //This function should only ever be called from within Character, meaning doc should always exist when this is called.
//Naturally, we don't include any non-player components in this update function. //Naturally, we don't include any non-player components in this update function.
@ -1306,12 +1318,12 @@ void Entity::Update(const float deltaTime) {
} }
if (m_ShouldDestroyAfterUpdate) { if (m_ShouldDestroyAfterUpdate) {
EntityManager::Instance()->DestroyEntity(this->GetObjectID()); Game::entityManager->DestroyEntity(this->GetObjectID());
} }
} }
void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxName, const std::string& status) { void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxName, const std::string& status) {
Entity* other = EntityManager::Instance()->GetEntity(otherEntity); Entity* other = Game::entityManager->GetEntity(otherEntity);
if (!other) return; if (!other) return;
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
@ -1325,7 +1337,7 @@ void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxN
} }
void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) { void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
auto* other = EntityManager::Instance()->GetEntity(otherEntity); auto* other = Game::entityManager->GetEntity(otherEntity);
if (!other) return; if (!other) return;
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
@ -1372,7 +1384,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
} }
void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) { void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) {
auto* other = EntityManager::Instance()->GetEntity(otherEntity); auto* other = Game::entityManager->GetEntity(otherEntity);
if (!other) return; if (!other) return;
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
@ -1526,13 +1538,13 @@ void Entity::Smash(const LWOOBJID source, const eKillType killType, const std::u
auto* destroyableComponent = GetComponent<DestroyableComponent>(); auto* destroyableComponent = GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr) { if (destroyableComponent == nullptr) {
Kill(EntityManager::Instance()->GetEntity(source)); Kill(Game::entityManager->GetEntity(source));
return; return;
} }
auto* possessorComponent = GetComponent<PossessorComponent>(); auto* possessorComponent = GetComponent<PossessorComponent>();
if (possessorComponent) { if (possessorComponent) {
if (possessorComponent->GetPossessable() != LWOOBJID_EMPTY) { if (possessorComponent->GetPossessable() != LWOOBJID_EMPTY) {
auto* mount = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable()); auto* mount = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
if (mount) possessorComponent->Dismount(mount, true); if (mount) possessorComponent->Dismount(mount, true);
} }
} }
@ -1560,20 +1572,20 @@ void Entity::Kill(Entity* murderer) {
} }
if (!IsPlayer()) { if (!IsPlayer()) {
EntityManager::Instance()->DestroyEntity(this); Game::entityManager->DestroyEntity(this);
} }
const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks"); const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks");
if (!grpNameQBShowBricks.empty()) { if (!grpNameQBShowBricks.empty()) {
auto spawners = dZoneManager::Instance()->GetSpawnersByName(grpNameQBShowBricks); auto spawners = Game::zoneManager->GetSpawnersByName(grpNameQBShowBricks);
Spawner* spawner = nullptr; Spawner* spawner = nullptr;
if (!spawners.empty()) { if (!spawners.empty()) {
spawner = spawners[0]; spawner = spawners[0];
} else { } else {
spawners = dZoneManager::Instance()->GetSpawnersInGroup(grpNameQBShowBricks); spawners = Game::zoneManager->GetSpawnersInGroup(grpNameQBShowBricks);
if (!spawners.empty()) { if (!spawners.empty()) {
spawner = spawners[0]; spawner = spawners[0];
@ -1741,7 +1753,7 @@ void Entity::CancelCallbackTimers() {
void Entity::ScheduleKillAfterUpdate(Entity* murderer) { void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
//if (m_Info.spawner) m_Info.spawner->ScheduleKill(this); //if (m_Info.spawner) m_Info.spawner->ScheduleKill(this);
EntityManager::Instance()->ScheduleForKill(this); Game::entityManager->ScheduleForKill(this);
if (murderer) m_ScheduleKiller = murderer; if (murderer) m_ScheduleKiller = murderer;
} }
@ -1785,7 +1797,7 @@ void Entity::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) {
Entity* Entity::GetOwner() const { Entity* Entity::GetOwner() const {
if (m_OwnerOverride != LWOOBJID_EMPTY) { if (m_OwnerOverride != LWOOBJID_EMPTY) {
auto* other = EntityManager::Instance()->GetEntity(m_OwnerOverride); auto* other = Game::entityManager->GetEntity(m_OwnerOverride);
if (other != nullptr) { if (other != nullptr) {
return other->GetOwner(); return other->GetOwner();
@ -1929,7 +1941,7 @@ void Entity::SetPosition(NiPoint3 position) {
vehicel->SetPosition(position); vehicel->SetPosition(position);
} }
EntityManager::Instance()->SerializeEntity(this); Game::entityManager->SerializeEntity(this);
} }
void Entity::SetRotation(NiQuaternion rotation) { void Entity::SetRotation(NiQuaternion rotation) {
@ -1957,7 +1969,7 @@ void Entity::SetRotation(NiQuaternion rotation) {
vehicel->SetRotation(rotation); vehicel->SetRotation(rotation);
} }
EntityManager::Instance()->SerializeEntity(this); Game::entityManager->SerializeEntity(this);
} }
bool Entity::GetBoolean(const std::u16string& name) const { bool Entity::GetBoolean(const std::u16string& name) const {
@ -2009,7 +2021,7 @@ std::vector<LWOOBJID>& Entity::GetTargetsInPhantom() {
for (auto i = 0u; i < m_TargetsInPhantom.size(); ++i) { for (auto i = 0u; i < m_TargetsInPhantom.size(); ++i) {
const auto id = m_TargetsInPhantom.at(i); const auto id = m_TargetsInPhantom.at(i);
auto* entity = EntityManager::Instance()->GetEntity(id); auto* entity = Game::entityManager->GetEntity(id);
if (entity == nullptr) { if (entity == nullptr) {
continue; continue;

View File

@ -85,6 +85,7 @@ public:
bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; } bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; }
bool GetIsGhostingCandidate() const; bool GetIsGhostingCandidate() const;
void SetIsGhostingCandidate(bool value) { m_IsGhostingCandidate = value; };
int8_t GetObservers() const; int8_t GetObservers() const;
@ -173,7 +174,6 @@ public:
void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType);
void ResetFlags();
void UpdateXMLDoc(tinyxml2::XMLDocument* doc); void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
void Update(float deltaTime); void Update(float deltaTime);

View File

@ -25,8 +25,6 @@
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#include "eReplicaPacketType.h" #include "eReplicaPacketType.h"
EntityManager* EntityManager::m_Address = nullptr;
// Configure which zones have ghosting disabled, mostly small worlds. // Configure which zones have ghosting disabled, mostly small worlds.
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = { std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
// Small zones // Small zones
@ -62,7 +60,7 @@ void EntityManager::Initialize() {
m_GhostingEnabled = std::find( m_GhostingEnabled = std::find(
m_GhostingExcludedZones.begin(), m_GhostingExcludedZones.begin(),
m_GhostingExcludedZones.end(), m_GhostingExcludedZones.end(),
dZoneManager::Instance()->GetZoneID().GetMapID() Game::zoneManager->GetZoneID().GetMapID()
) == m_GhostingExcludedZones.end(); ) == m_GhostingExcludedZones.end();
// grab hardcore mode settings and load them with sane defaults // grab hardcore mode settings and load them with sane defaults
@ -77,10 +75,7 @@ void EntityManager::Initialize() {
// If cloneID is not zero, then hardcore mode is disabled // If cloneID is not zero, then hardcore mode is disabled
// aka minigames and props // aka minigames and props
if (dZoneManager::Instance()->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false; if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
}
EntityManager::~EntityManager() {
} }
Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentEntity, const bool controller, const LWOOBJID explicitId) { Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentEntity, const bool controller, const LWOOBJID explicitId) {
@ -588,12 +583,6 @@ bool EntityManager::GetGhostingEnabled() const {
return m_GhostingEnabled; return m_GhostingEnabled;
} }
void EntityManager::ResetFlags() {
for (const auto& e : m_Entities) {
e.second->ResetFlags();
}
}
void EntityManager::ScheduleForKill(Entity* entity) { void EntityManager::ScheduleForKill(Entity* entity) {
// Deactivate switches if they die // Deactivate switches if they die
if (!entity) if (!entity)

View File

@ -1,12 +1,13 @@
#ifndef ENTITYMANAGER_H #ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H #define ENTITYMANAGER_H
#include "dCommonVars.h"
#include <map> #include <map>
#include <stack> #include <stack>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include "dCommonVars.h"
class Entity; class Entity;
class EntityInfo; class EntityInfo;
class Player; class Player;
@ -17,19 +18,8 @@ struct SystemAddress;
class EntityManager { class EntityManager {
public: public:
static EntityManager* Instance() {
if (!m_Address) {
m_Address = new EntityManager();
m_Address->Initialize();
}
return m_Address;
}
void Initialize(); void Initialize();
~EntityManager();
void UpdateEntities(float deltaTime); void UpdateEntities(float deltaTime);
Entity* CreateEntity(EntityInfo info, User* user = nullptr, Entity* parentEntity = nullptr, bool controller = false, LWOOBJID explicitId = LWOOBJID_EMPTY); Entity* CreateEntity(EntityInfo info, User* user = nullptr, Entity* parentEntity = nullptr, bool controller = false, LWOOBJID explicitId = LWOOBJID_EMPTY);
void DestroyEntity(const LWOOBJID& objectID); void DestroyEntity(const LWOOBJID& objectID);
@ -69,8 +59,6 @@ public:
Entity* GetGhostCandidate(int32_t id); Entity* GetGhostCandidate(int32_t id);
bool GetGhostingEnabled() const; bool GetGhostingEnabled() const;
void ResetFlags();
void ScheduleForKill(Entity* entity); void ScheduleForKill(Entity* entity);
void ScheduleForDeletion(LWOOBJID entity); void ScheduleForDeletion(LWOOBJID entity);
@ -89,7 +77,6 @@ private:
void KillEntities(); void KillEntities();
void DeleteEntities(); void DeleteEntities();
static EntityManager* m_Address; //For singleton method
static std::vector<LWOMAPID> m_GhostingExcludedZones; static std::vector<LWOMAPID> m_GhostingExcludedZones;
static std::vector<LOT> m_GhostingExcludedLOTs; static std::vector<LOT> m_GhostingExcludedLOTs;

View File

@ -1,5 +1,8 @@
#include "LeaderboardManager.h" #include "LeaderboardManager.h"
#include <sstream>
#include <utility> #include <utility>
#include "Database.h" #include "Database.h"
#include "EntityManager.h" #include "EntityManager.h"
#include "Character.h" #include "Character.h"
@ -10,461 +13,400 @@
#include "CDClientManager.h" #include "CDClientManager.h"
#include "GeneralUtils.h" #include "GeneralUtils.h"
#include "Entity.h" #include "Entity.h"
#include "LDFFormat.h"
#include "DluAssert.h"
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
#include "Metrics.hpp"
Leaderboard::Leaderboard(uint32_t gameID, uint32_t infoType, bool weekly, std::vector<LeaderboardEntry> entries, namespace LeaderboardManager {
LWOOBJID relatedPlayer, LeaderboardType leaderboardType) { std::map<GameID, Leaderboard::Type> leaderboardCache;
this->relatedPlayer = relatedPlayer; }
Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type leaderboardType) {
this->gameID = gameID; this->gameID = gameID;
this->weekly = weekly; this->weekly = weekly;
this->infoType = infoType; this->infoType = infoType;
this->entries = std::move(entries);
this->leaderboardType = leaderboardType; this->leaderboardType = leaderboardType;
this->relatedPlayer = relatedPlayer;
} }
std::u16string Leaderboard::ToString() const { Leaderboard::~Leaderboard() {
std::string leaderboard; Clear();
}
leaderboard += "ADO.Result=7:1\n"; void Leaderboard::Clear() {
leaderboard += "Result.Count=1:1\n"; for (auto& entry : entries) for (auto ldfData : entry) delete ldfData;
leaderboard += "Result[0].Index=0:RowNumber\n"; }
leaderboard += "Result[0].RowCount=1:" + std::to_string(entries.size()) + "\n";
auto index = 0; inline void WriteLeaderboardRow(std::ostringstream& leaderboard, const uint32_t& index, LDFBaseData* data) {
for (const auto& entry : entries) { leaderboard << "\nResult[0].Row[" << index << "]." << data->GetString();
leaderboard += "Result[0].Row[" + std::to_string(index) + "].LastPlayed=8:" + std::to_string(entry.lastPlayed) + "\n"; }
leaderboard += "Result[0].Row[" + std::to_string(index) + "].CharacterID=8:" + std::to_string(entry.playerID) + "\n";
leaderboard += "Result[0].Row[" + std::to_string(index) + "].NumPlayed=1:1\n";
leaderboard += "Result[0].Row[" + std::to_string(index) + "].RowNumber=8:" + std::to_string(entry.placement) + "\n";
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Time=1:" + std::to_string(entry.time) + "\n";
// Only these minigames have a points system void Leaderboard::Serialize(RakNet::BitStream* bitStream) const {
if (leaderboardType == Survival || leaderboardType == ShootingGallery) { bitStream->Write(gameID);
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Points=1:" + std::to_string(entry.score) + "\n"; bitStream->Write(infoType);
} else if (leaderboardType == SurvivalNS) {
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Wave=1:" + std::to_string(entry.score) + "\n"; std::ostringstream leaderboard;
leaderboard << "ADO.Result=7:1"; // Unused in 1.10.64, but is in captures
leaderboard << "\nResult.Count=1:1"; // number of results, always 1
if (!this->entries.empty()) leaderboard << "\nResult[0].Index=0:RowNumber"; // "Primary key". Live doesn't include this if there are no entries.
leaderboard << "\nResult[0].RowCount=1:" << entries.size();
int32_t rowNumber = 0;
for (auto& entry : entries) {
for (auto* data : entry) {
WriteLeaderboardRow(leaderboard, rowNumber, data);
}
rowNumber++;
} }
leaderboard += "Result[0].Row[" + std::to_string(index) + "].name=0:" + entry.playerName + "\n"; // Serialize the thing to a BitStream
index++; uint32_t leaderboardSize = leaderboard.tellp();
bitStream->Write<uint32_t>(leaderboardSize);
// Doing this all in 1 call so there is no possbility of a dangling pointer.
bitStream->WriteAlignedBytes(reinterpret_cast<const unsigned char*>(GeneralUtils::ASCIIToUTF16(leaderboard.str()).c_str()), leaderboardSize * sizeof(char16_t));
if (leaderboardSize > 0) bitStream->Write<uint16_t>(0);
bitStream->Write0();
bitStream->Write0();
}
void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
Clear();
if (rows->rowsCount() == 0) return;
this->entries.reserve(rows->rowsCount());
while (rows->next()) {
constexpr int32_t MAX_NUM_DATA_PER_ROW = 9;
this->entries.push_back(std::vector<LDFBaseData*>());
auto& entry = this->entries.back();
entry.reserve(MAX_NUM_DATA_PER_ROW);
entry.push_back(new LDFData<uint64_t>(u"CharacterID", rows->getInt("character_id")));
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", rows->getUInt64("lastPlayed")));
entry.push_back(new LDFData<int32_t>(u"NumPlayed", rows->getInt("timesPlayed")));
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str())));
entry.push_back(new LDFData<uint64_t>(u"RowNumber", rows->getInt("ranking")));
switch (leaderboardType) {
case Type::ShootingGallery:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
// Score:1
entry.push_back(new LDFData<int32_t>(u"Streak", rows->getInt("secondaryScore")));
// Streak:1
entry.push_back(new LDFData<float>(u"HitPercentage", (rows->getInt("tertiaryScore") / 100.0f)));
// HitPercentage:3 between 0 and 1
break;
case Type::Racing:
entry.push_back(new LDFData<float>(u"BestTime", rows->getDouble("primaryScore")));
// BestLapTime:3
entry.push_back(new LDFData<float>(u"BestLapTime", rows->getDouble("secondaryScore")));
// BestTime:3
entry.push_back(new LDFData<int32_t>(u"License", 1));
// License:1 - 1 if player has completed mission 637 and 0 otherwise
entry.push_back(new LDFData<int32_t>(u"NumWins", rows->getInt("numWins")));
// NumWins:1
break;
case Type::UnusedLeaderboard4:
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
// Points:1
break;
case Type::MonumentRace:
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
// Time:1(?)
break;
case Type::FootRace:
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
// Time:1
break;
case Type::Survival:
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
// Points:1
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
// Time:1
break;
case Type::SurvivalNS:
entry.push_back(new LDFData<int32_t>(u"Wave", rows->getInt("primaryScore")));
// Wave:1
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
// Time:1
break;
case Type::Donations:
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
// Score:1
break;
case Type::None:
// This type is included here simply to resolve a compiler warning on mac about unused enum types
break;
default:
break;
}
} }
return GeneralUtils::UTF8ToUTF16(leaderboard);
} }
std::vector<LeaderboardEntry> Leaderboard::GetEntries() { const std::string_view Leaderboard::GetOrdering(Leaderboard::Type leaderboardType) {
return entries; // Use a switch case and return desc for all 3 columns if higher is better and asc if lower is better
switch (leaderboardType) {
case Type::Racing:
case Type::MonumentRace:
return "primaryScore ASC, secondaryScore ASC, tertiaryScore ASC";
case Type::Survival:
return Game::config->GetValue("classic_survival_scoring") == "1" ?
"secondaryScore DESC, primaryScore DESC, tertiaryScore DESC" :
"primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
case Type::SurvivalNS:
return "primaryScore DESC, secondaryScore ASC, tertiaryScore DESC";
case Type::ShootingGallery:
case Type::FootRace:
case Type::UnusedLeaderboard4:
case Type::Donations:
case Type::None:
default:
return "primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
}
} }
uint32_t Leaderboard::GetGameID() const { void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t resultEnd) {
return gameID; resultStart++;
resultEnd++;
// We need everything except 1 column so i'm selecting * from leaderboard
const std::string queryBase =
R"QUERY(
WITH leaderboardsRanked AS (
SELECT leaderboard.*, charinfo.name,
RANK() OVER
(
ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC
) AS ranking
FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id
WHERE game_id = ? %s
),
myStanding AS (
SELECT
ranking as myRank
FROM leaderboardsRanked
WHERE id = ?
),
lowestRanking AS (
SELECT MAX(ranking) AS lowestRank
FROM leaderboardsRanked
)
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
WHERE leaderboardsRanked.ranking
BETWEEN
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
AND
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
ORDER BY ranking ASC;
)QUERY";
std::string friendsFilter =
R"QUERY(
AND (
character_id IN (
SELECT fr.requested_player FROM (
SELECT CASE
WHEN player_id = ? THEN friend_id
WHEN friend_id = ? THEN player_id
END AS requested_player
FROM friends
) AS fr
JOIN charinfo AS ci
ON ci.id = fr.requested_player
WHERE fr.requested_player IS NOT NULL
)
OR character_id = ?
)
)QUERY";
std::string weeklyFilter = " AND UNIX_TIMESTAMP(last_played) BETWEEN UNIX_TIMESTAMP(date_sub(now(),INTERVAL 1 WEEK)) AND UNIX_TIMESTAMP(now()) ";
std::string filter;
// Setup our filter based on the query type
if (this->infoType == InfoType::Friends) filter += friendsFilter;
if (this->weekly) filter += weeklyFilter;
const auto orderBase = GetOrdering(this->leaderboardType);
// For top query, we want to just rank all scores, but for all others we need the scores around a specific player
std::string baseLookup;
if (this->infoType == InfoType::Top) {
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " ORDER BY ";
baseLookup += orderBase.data();
} else {
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " AND character_id = ";
baseLookup += std::to_string(static_cast<uint32_t>(this->relatedPlayer));
}
baseLookup += " LIMIT 1";
Game::logger->LogDebug("LeaderboardManager", "query is %s", baseLookup.c_str());
std::unique_ptr<sql::PreparedStatement> baseQuery(Database::CreatePreppedStmt(baseLookup));
baseQuery->setInt(1, this->gameID);
std::unique_ptr<sql::ResultSet> baseResult(baseQuery->executeQuery());
if (!baseResult->next()) return; // In this case, there are no entries in the leaderboard for this game.
uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id");
// Create and execute the actual save here. Using a heap allocated buffer to avoid stack overflow
constexpr uint16_t STRING_LENGTH = 4096;
std::unique_ptr<char[]> lookupBuffer = std::make_unique<char[]>(STRING_LENGTH);
int32_t res = snprintf(lookupBuffer.get(), STRING_LENGTH, queryBase.c_str(), orderBase.data(), filter.c_str(), resultStart, resultEnd);
DluAssert(res != -1);
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookupBuffer.get()));
Game::logger->LogDebug("LeaderboardManager", "Query is %s vars are %i %i %i", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
query->setInt(1, this->gameID);
if (this->infoType == InfoType::Friends) {
query->setInt(2, this->relatedPlayer);
query->setInt(3, this->relatedPlayer);
query->setInt(4, this->relatedPlayer);
query->setInt(5, relatedPlayerLeaderboardId);
} else {
query->setInt(2, relatedPlayerLeaderboardId);
}
std::unique_ptr<sql::ResultSet> result(query->executeQuery());
QueryToLdf(result);
} }
uint32_t Leaderboard::GetInfoType() const { void Leaderboard::Send(const LWOOBJID targetID) const {
return infoType; auto* player = Game::entityManager->GetEntity(relatedPlayer);
}
void Leaderboard::Send(LWOOBJID targetID) const {
auto* player = EntityManager::Instance()->GetEntity(relatedPlayer);
if (player != nullptr) { if (player != nullptr) {
GameMessages::SendActivitySummaryLeaderboardData(targetID, this, player->GetSystemAddress()); GameMessages::SendActivitySummaryLeaderboardData(targetID, this, player->GetSystemAddress());
} }
} }
void LeaderboardManager::SaveScore(LWOOBJID playerID, uint32_t gameID, uint32_t score, uint32_t time) { std::string FormatInsert(const Leaderboard::Type& type, const Score& score, const bool useUpdate) {
const auto* player = EntityManager::Instance()->GetEntity(playerID); std::string insertStatement;
if (player == nullptr) if (useUpdate) {
return; insertStatement =
R"QUERY(
UPDATE leaderboard
SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;
)QUERY";
} else {
insertStatement =
R"QUERY(
INSERT leaderboard SET
primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
character_id = ?, game_id = ?;
)QUERY";
}
auto* character = player->GetCharacter(); constexpr uint16_t STRING_LENGTH = 400;
if (character == nullptr) // Then fill in our score
return; char finishedQuery[STRING_LENGTH];
int32_t res = snprintf(finishedQuery, STRING_LENGTH, insertStatement.c_str(), score.GetPrimaryScore(), score.GetSecondaryScore(), score.GetTertiaryScore());
DluAssert(res != -1);
return finishedQuery;
}
auto* select = Database::CreatePreppedStmt("SELECT time, score FROM leaderboard WHERE character_id = ? AND game_id = ?;"); void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) {
const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId);
select->setUInt64(1, character->GetID()); std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt("SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;"));
select->setInt(2, gameID); query->setInt(1, playerID);
query->setInt(2, activityId);
auto any = false; std::unique_ptr<sql::ResultSet> myScoreResult(query->executeQuery());
auto* result = select->executeQuery();
auto leaderboardType = GetLeaderboardType(gameID);
// Check if the new score is a high score
while (result->next()) {
any = true;
const auto storedTime = result->getInt(1);
const auto storedScore = result->getInt(2);
auto highscore = true;
bool classicSurvivalScoring = Game::config->GetValue("classic_survival_scoring") == "1";
std::string saveQuery("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;");
Score newScore(primaryScore, secondaryScore, tertiaryScore);
if (myScoreResult->next()) {
Score oldScore;
bool lowerScoreBetter = false;
switch (leaderboardType) { switch (leaderboardType) {
case ShootingGallery: // Higher score better
if (score <= storedScore) case Leaderboard::Type::ShootingGallery: {
highscore = false; oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
oldScore.SetTertiaryScore(myScoreResult->getInt("tertiaryScore"));
break; break;
case Racing: }
if (time >= storedTime) case Leaderboard::Type::FootRace: {
highscore = false; oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
break; break;
case MonumentRace: }
if (time >= storedTime) case Leaderboard::Type::Survival: {
highscore = false; oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
break; break;
case FootRace: }
if (time <= storedTime) case Leaderboard::Type::SurvivalNS: {
highscore = false; oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
break; break;
case Survival: }
if (classicSurvivalScoring) { case Leaderboard::Type::UnusedLeaderboard4:
if (time <= storedTime) { // Based on time (LU live) case Leaderboard::Type::Donations: {
highscore = false; oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
newScore.SetPrimaryScore(oldScore.GetPrimaryScore() + newScore.GetPrimaryScore());
break;
}
case Leaderboard::Type::Racing: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
// For wins we dont care about the score, just the time, so zero out the tertiary.
// Wins are updated later.
oldScore.SetTertiaryScore(0);
newScore.SetTertiaryScore(0);
lowerScoreBetter = true;
break;
}
case Leaderboard::Type::MonumentRace: {
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
lowerScoreBetter = true;
// Do score checking here
break;
}
case Leaderboard::Type::None:
default:
Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i for game %i. Cannot save score!", leaderboardType, activityId);
return;
}
bool newHighScore = lowerScoreBetter ? newScore < oldScore : newScore > oldScore;
// Nimbus station has a weird leaderboard where we need a custom scoring system
if (leaderboardType == Leaderboard::Type::SurvivalNS) {
newHighScore = newScore.GetPrimaryScore() > oldScore.GetPrimaryScore() ||
(newScore.GetPrimaryScore() == oldScore.GetPrimaryScore() && newScore.GetSecondaryScore() < oldScore.GetSecondaryScore());
} else if (leaderboardType == Leaderboard::Type::Survival && Game::config->GetValue("classic_survival_scoring") == "1") {
Score oldScoreFlipped(oldScore.GetSecondaryScore(), oldScore.GetPrimaryScore());
Score newScoreFlipped(newScore.GetSecondaryScore(), newScore.GetPrimaryScore());
newHighScore = newScoreFlipped > oldScoreFlipped;
}
if (newHighScore) {
saveQuery = FormatInsert(leaderboardType, newScore, true);
} }
} else { } else {
if (score <= storedScore) // Based on score (DLU) saveQuery = FormatInsert(leaderboardType, newScore, false);
highscore = false;
}
break;
case SurvivalNS:
if (!(score > storedScore || (time < storedTime && score >= storedScore)))
highscore = false;
break;
default:
highscore = false;
} }
Game::logger->Log("LeaderboardManager", "save query %s %i %i", saveQuery.c_str(), playerID, activityId);
std::unique_ptr<sql::PreparedStatement> saveStatement(Database::CreatePreppedStmt(saveQuery));
saveStatement->setInt(1, playerID);
saveStatement->setInt(2, activityId);
saveStatement->execute();
if (!highscore) { // track wins separately
delete select; if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) {
delete result; std::unique_ptr<sql::PreparedStatement> winUpdate(Database::CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;"));
return; winUpdate->setInt(1, playerID);
} winUpdate->setInt(2, activityId);
} winUpdate->execute();
delete select;
delete result;
if (any) {
auto* statement = Database::CreatePreppedStmt("UPDATE leaderboard SET time = ?, score = ?, last_played=SYSDATE() WHERE character_id = ? AND game_id = ?;");
statement->setInt(1, time);
statement->setInt(2, score);
statement->setUInt64(3, character->GetID());
statement->setInt(4, gameID);
statement->execute();
delete statement;
} else {
// Note: last_played will be set to SYSDATE() by default when inserting into leaderboard
auto* statement = Database::CreatePreppedStmt("INSERT INTO leaderboard (character_id, game_id, time, score) VALUES (?, ?, ?, ?);");
statement->setUInt64(1, character->GetID());
statement->setInt(2, gameID);
statement->setInt(3, time);
statement->setInt(4, score);
statement->execute();
delete statement;
} }
} }
Leaderboard* LeaderboardManager::GetLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID playerID) { void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t resultStart, const uint32_t resultEnd) {
auto leaderboardType = GetLeaderboardType(gameID); Leaderboard leaderboard(gameID, infoType, weekly, playerID, GetLeaderboardType(gameID));
leaderboard.SetupLeaderboard(weekly, resultStart, resultEnd);
std::string query; leaderboard.Send(targetID);
bool classicSurvivalScoring = Game::config->GetValue("classic_survival_scoring") == "1";
switch (infoType) {
case InfoType::Standings:
switch (leaderboardType) {
case ShootingGallery:
query = standingsScoreQuery; // Shooting gallery is based on the highest score.
break;
case FootRace:
query = standingsTimeQuery; // The higher your time, the better for FootRace.
break;
case Survival:
query = classicSurvivalScoring ? standingsTimeQuery : standingsScoreQuery;
break;
case SurvivalNS:
query = standingsScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
break;
default:
query = standingsTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
}
break;
case InfoType::Friends:
switch (leaderboardType) {
case ShootingGallery:
query = friendsScoreQuery; // Shooting gallery is based on the highest score.
break;
case FootRace:
query = friendsTimeQuery; // The higher your time, the better for FootRace.
break;
case Survival:
query = classicSurvivalScoring ? friendsTimeQuery : friendsScoreQuery;
break;
case SurvivalNS:
query = friendsScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
break;
default:
query = friendsTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
}
break;
default:
switch (leaderboardType) {
case ShootingGallery:
query = topPlayersScoreQuery; // Shooting gallery is based on the highest score.
break;
case FootRace:
query = topPlayersTimeQuery; // The higher your time, the better for FootRace.
break;
case Survival:
query = classicSurvivalScoring ? topPlayersTimeQuery : topPlayersScoreQuery;
break;
case SurvivalNS:
query = topPlayersScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
break;
default:
query = topPlayersTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
}
}
auto* statement = Database::CreatePreppedStmt(query);
statement->setUInt(1, gameID);
// Only the standings and friends leaderboards require the character ID to be set
if (infoType == Standings || infoType == Friends) {
auto characterID = 0;
const auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player != nullptr) {
auto* character = player->GetCharacter();
if (character != nullptr)
characterID = character->GetID();
}
statement->setUInt64(2, characterID);
}
auto* res = statement->executeQuery();
std::vector<LeaderboardEntry> entries{};
uint32_t index = 0;
while (res->next()) {
LeaderboardEntry entry;
entry.playerID = res->getUInt64(4);
entry.playerName = res->getString(5);
entry.time = res->getUInt(1);
entry.score = res->getUInt(2);
entry.placement = res->getUInt(3);
entry.lastPlayed = res->getUInt(6);
entries.push_back(entry);
index++;
}
delete res;
delete statement;
return new Leaderboard(gameID, infoType, weekly, entries, playerID, leaderboardType);
} }
void LeaderboardManager::SendLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID targetID, Leaderboard::Type LeaderboardManager::GetLeaderboardType(const GameID gameID) {
LWOOBJID playerID) { auto lookup = leaderboardCache.find(gameID);
const auto* leaderboard = LeaderboardManager::GetLeaderboard(gameID, infoType, weekly, playerID); if (lookup != leaderboardCache.end()) return lookup->second;
leaderboard->Send(targetID);
delete leaderboard;
}
LeaderboardType LeaderboardManager::GetLeaderboardType(uint32_t gameID) {
auto* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>(); auto* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([=](const CDActivities& entry) { std::vector<CDActivities> activities = activitiesTable->Query([gameID](const CDActivities& entry) {
return (entry.ActivityID == gameID); return entry.ActivityID == gameID;
}); });
auto type = !activities.empty() ? static_cast<Leaderboard::Type>(activities.at(0).leaderboardType) : Leaderboard::Type::None;
for (const auto& activity : activities) { leaderboardCache.insert_or_assign(gameID, type);
return static_cast<LeaderboardType>(activity.leaderboardType); return type;
}
return LeaderboardType::None;
} }
const std::string LeaderboardManager::topPlayersScoreQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
"RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
"INNER JOIN charinfo c ON l.character_id = c.id "
"WHERE l.game_id = ? "
"ORDER BY leaderboard_rank) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales LIMIT 11;";
const std::string LeaderboardManager::friendsScoreQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
" RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" INNER JOIN friends f ON f.player_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
" personal_values AS ( "
" SELECT id as related_player_id, "
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
const std::string LeaderboardManager::standingsScoreQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
" RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
"personal_values AS ( "
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
const std::string LeaderboardManager::topPlayersScoreQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
"RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
" FROM leaderboard l "
"INNER JOIN charinfo c ON l.character_id = c.id "
"WHERE l.game_id = ? "
"ORDER BY leaderboard_rank) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales LIMIT 11;";
const std::string LeaderboardManager::friendsScoreQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
" RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" INNER JOIN friends f ON f.player_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
" personal_values AS ( "
" SELECT id as related_player_id, "
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
const std::string LeaderboardManager::standingsScoreQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
" RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
"personal_values AS ( "
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
const std::string LeaderboardManager::topPlayersTimeQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
"RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
"INNER JOIN charinfo c ON l.character_id = c.id "
"WHERE l.game_id = ? "
"ORDER BY leaderboard_rank) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales LIMIT 11;";
const std::string LeaderboardManager::friendsTimeQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
" RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" INNER JOIN friends f ON f.player_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
" personal_values AS ( "
" SELECT id as related_player_id, "
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
const std::string LeaderboardManager::standingsTimeQuery =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
" RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
"personal_values AS ( "
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
const std::string LeaderboardManager::topPlayersTimeQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
"RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
"INNER JOIN charinfo c ON l.character_id = c.id "
"WHERE l.game_id = ? "
"ORDER BY leaderboard_rank) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales LIMIT 11;";
const std::string LeaderboardManager::friendsTimeQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
" RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" INNER JOIN friends f ON f.player_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
" personal_values AS ( "
" SELECT id as related_player_id, "
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
const std::string LeaderboardManager::standingsTimeQueryAsc =
"WITH leaderboard_vales AS ( "
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
" RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
" FROM leaderboard l "
" INNER JOIN charinfo c ON l.character_id = c.id "
" WHERE l.game_id = ? "
" ORDER BY leaderboard_rank), "
"personal_values AS ( "
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
"SELECT time, score, leaderboard_rank, id, name, last_played "
"FROM leaderboard_vales, personal_values "
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";

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