mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-23 23:24:21 +00:00
Compare commits
1 Commits
EmosewaMC-
...
csr_comman
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d77a1a92bf |
@@ -25,14 +25,11 @@ Darkflame Universe is a server emulator and does not distribute any LEGO® Unive
|
|||||||
You must use Version 2 if you must run the server under WSL. Not doing so will result in save data loss.
|
You must use Version 2 if you must run the server under WSL. Not doing so will result in save data loss.
|
||||||
* Single player installs now no longer require building the server from source or installing development tools.
|
* Single player installs now no longer require building the server from source or installing development tools.
|
||||||
* Download the [latest windows release](https://github.com/DarkflameUniverse/DarkflameServer/releases) (or whichever release you need) and extract the files into a folder inside your client. Note that this setup is expecting that when double clicking the folder that you put in the same folder as `legouniverse.exe`, the file `MasterServer.exe` is in there.
|
* Download the [latest windows release](https://github.com/DarkflameUniverse/DarkflameServer/releases) (or whichever release you need) and extract the files into a folder inside your client. Note that this setup is expecting that when double clicking the folder that you put in the same folder as `legouniverse.exe`, the file `MasterServer.exe` is in there.
|
||||||
* To connect to the server, either delete the file `boot.cfg` which is found in your LEGO Universe client, rename the file `boot.cfg` to something else or follow the steps [here](#allowing-a-user-to-connect-to-your-server) if you wish to keep the file.
|
* You should be able to see the folder with the server files in the same folder as `legouniverse.exe`.
|
||||||
* If you would like to put the server in a different location, make sure client_location has the full path to the folder with `legouniverse.exe` in it. You can then exclude the `msvc` folder from the image below.
|
* Go into the server files folder and open `sharedconfig.ini`. Find the line that says `client_location` and put `..` after it so the line reads `client_location=..`.
|
||||||
* You should be able to see the folder with the server files in the same folder as `legouniverse.exe`. An example valid configuration is below with the 3 highlighted items.
|
|
||||||
# <img style="float: left; padding-right: 5px" src="docs/setup.png">
|
|
||||||
* The inside of the `msvc` folder (or whatever you choose to name this folder) should look something like this
|
|
||||||
# <img style="float: left; padding-right: 5px" src="docs/valid_server.png">
|
|
||||||
* To run the server, double-click `MasterServer.exe`.
|
* To run the server, double-click `MasterServer.exe`.
|
||||||
* You will be asked to create an account the first time you run the server. After you have created the account, the server will shutdown and need to be restarted.
|
* You will be asked to create an account the first time you run the server. After you have created the account, the server will shutdown and need to be restarted.
|
||||||
|
* To connect to the server, either delete the file `boot.cfg` which is found in your LEGO Universe client, rename the file `boot.cfg` to something else or follow the steps [here](#allowing-a-user-to-connect-to-your-server) if you wish to keep the file.
|
||||||
* When shutting down the server, it is highly recommended to click the `MasterServer.exe` window and hold `ctrl` while pressing `c` to stop the server.
|
* When shutting down the server, it is highly recommended to click the `MasterServer.exe` window and hold `ctrl` while pressing `c` to stop the server.
|
||||||
* We are working on a way to make it so when you close the game, the server stops automatically alongside when you open the game, the server starts automatically.
|
* We are working on a way to make it so when you close the game, the server stops automatically alongside when you open the game, the server starts automatically.
|
||||||
* If you are not setting a server up on mac, you can ignore this note
|
* If you are not setting a server up on mac, you can ignore this note
|
||||||
|
|||||||
@@ -70,15 +70,12 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort = 1500;
|
uint32_t masterPort = 1500;
|
||||||
std::string masterPassword;
|
|
||||||
|
|
||||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
if (masterInfo) {
|
if (masterInfo) {
|
||||||
masterIP = masterInfo->ip;
|
masterIP = masterInfo->ip;
|
||||||
masterPort = masterInfo->port;
|
masterPort = masterInfo->port;
|
||||||
masterPassword = masterInfo->password;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
|
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
|
||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
@@ -92,7 +89,7 @@ int main(int argc, char** argv) {
|
|||||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||||
|
|
||||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal, masterPassword);
|
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal);
|
||||||
|
|
||||||
//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();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ set(DCHATSERVER_SOURCES
|
|||||||
"PlayerContainer.cpp"
|
"PlayerContainer.cpp"
|
||||||
"ChatWebAPI.cpp"
|
"ChatWebAPI.cpp"
|
||||||
"JSONUtils.cpp"
|
"JSONUtils.cpp"
|
||||||
|
"CSRCommandHandler.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(ChatServer "ChatServer.cpp")
|
add_executable(ChatServer "ChatServer.cpp")
|
||||||
|
|||||||
353
dChatServer/CSRCommandHandler.cpp
Normal file
353
dChatServer/CSRCommandHandler.cpp
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
#include "CSRCommandHandler.h"
|
||||||
|
#include "eCSRCommand.h"
|
||||||
|
#include "eHTTPStatusCode.h"
|
||||||
|
#include "JSONUtils.h"
|
||||||
|
#include "magic_enum.hpp"
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
void CSRCommandHandler::HandleCSRCommand(HTTPReply& reply, const json& data) {
|
||||||
|
auto check = JSONUtils::CheckRequiredData(data, { "command" });
|
||||||
|
if (!check.empty()) {
|
||||||
|
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
||||||
|
reply.message = check;
|
||||||
|
} else {
|
||||||
|
// get command from json
|
||||||
|
std::string command_string = data["command"];
|
||||||
|
// upper
|
||||||
|
std::transform(command_string.begin(), command_string.end(), command_string.begin(), ::toupper);
|
||||||
|
eCSRCommand command = magic_enum::enum_cast<eCSRCommand>(command_string).value_or(eCSRCommand::INVALID);
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case eCSRCommand::QUERY_SERVER_STATUS:
|
||||||
|
QueryServerStatus(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::QUERY_CHARACTER_LOCATION:
|
||||||
|
QueryCharacterLocation(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::QUERY_CHARACTER_ONLINE_STATUS:
|
||||||
|
QueryCharacterOnlineStatus(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::INVENTORY_ADD_ITEM:
|
||||||
|
InventoryAddItem(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::INVENTORY_DELETE_ITEM:
|
||||||
|
InventoryDeleteItem(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_MUTE_ACCOUNT:
|
||||||
|
ModerateMuteAccount(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_BAN_ACCOUNT:
|
||||||
|
ModerateBanAccount(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_EDUCATE_CHARACTER:
|
||||||
|
ModerateEducateCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_KICK_CHARACTER:
|
||||||
|
ModerateKickCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_WARN_CHARACTER:
|
||||||
|
ModerateWarnCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_RENAME_CHARACTER:
|
||||||
|
ModerateRenameCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_DELETE_CHARACTER_FRIEND:
|
||||||
|
ModerateDeleteCharacterFriend(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_KILL_CHARACTER:
|
||||||
|
ModerateKillCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_HEALTH:
|
||||||
|
UpdateCharacterHealth(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_ARMOR:
|
||||||
|
UpdateCharacterArmor(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_IMAGINATION:
|
||||||
|
UpdateCharacterImagination(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_MAX_HEALTH:
|
||||||
|
UpdateCharacterMaxHealth(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_MAX_ARMOR:
|
||||||
|
UpdateCharacterMaxArmor(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_MAX_IMAGINATION:
|
||||||
|
UpdateCharacterMaxImagination(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_CURRENCY:
|
||||||
|
UpdateCharacterCurrency(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_REPUTATION:
|
||||||
|
UpdateCharacterReputation(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_LEGO_SCORE:
|
||||||
|
UpdateCharacterLegoScore(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_EMOTES:
|
||||||
|
UpdateCharacterEmotes(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_ADD_ACHIEVEMENT:
|
||||||
|
UpdateCharacterAddAchievement(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_COMPLETE_ACHIEVEMENT:
|
||||||
|
UpdateCharacterCompleteAchievement(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_REMOVE_ACHIEVEMENT:
|
||||||
|
UpdateCharacterRemoveAchievement(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_POSITION_OFFLINE:
|
||||||
|
UpdateCharacterPositionOffline(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UPDATE_CHARACTER_INV_SLOT_AMOUNT:
|
||||||
|
UpdateCharacterInvSlotAmount(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UTILITY_SAVE_CHARACTER:
|
||||||
|
UtilitySaveCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UTILITY_SEND_MAIL:
|
||||||
|
UtilitySendMail(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::UTILITY_GIVE_ITEM_TO_ALL_PLAYERS_ONLINE:
|
||||||
|
UtilityGiveItemToAllPlayersOnline(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::METRICS_CONFIGURE:
|
||||||
|
MetricsConfigure(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::DISABLE_ZONE:
|
||||||
|
DisableZone(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::INIT_DONATION_AMOUNT:
|
||||||
|
InitDonationAmount(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::KILL_SERVERS_COUNTDOWN:
|
||||||
|
KillServersCountdown(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::DISABLE_FAQ:
|
||||||
|
DisableFAQ(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::THROTTLEQUEUE:
|
||||||
|
ThrottleQueue(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::GATEGM_ACCESS:
|
||||||
|
GateGMAccess(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::RECONNECT_CRISP:
|
||||||
|
ReconnectCrisp(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::MODERATE_KICK_ACCOUNT:
|
||||||
|
ModerateKickAccount(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::TOGGLE_CRISP_SERVER:
|
||||||
|
ToggleCrispServer(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::QUICK_DRAIN_SERVER:
|
||||||
|
QuickDrainServer(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::QUICK_DRAIN_SERVER_RENEW:
|
||||||
|
QuickDrainServerRenew(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::REPLICATE_CHARACTER:
|
||||||
|
ReplicateCharacter(reply, data);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::GET_SERVER_STATUS:
|
||||||
|
GetServerStatus(reply);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::RELOAD_SERVER_INIS:
|
||||||
|
ReloadServerINIs(reply);
|
||||||
|
break;
|
||||||
|
case eCSRCommand::INVALID:
|
||||||
|
default:
|
||||||
|
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
||||||
|
reply.message = "{\"error\":\"Invalid Command\"}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSRCommandHandler::QueryServerStatus(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::QueryCharacterLocation(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::QueryCharacterOnlineStatus(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::InventoryAddItem(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::InventoryDeleteItem(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateMuteAccount(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateBanAccount(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateEducateCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateKickCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateWarnCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateRenameCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateDeleteCharacterFriend(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateKillCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterHealth(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterArmor(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterImagination(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterMaxHealth(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterMaxArmor(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterMaxImagination(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterCurrency(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterReputation(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterLegoScore(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterEmotes(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterAddAchievement(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterCompleteAchievement(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterRemoveAchievement(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterPositionOffline(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UpdateCharacterInvSlotAmount(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UtilitySaveCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UtilitySendMail(HTTPReply& reply, const json& data) {
|
||||||
|
|
||||||
|
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::UtilityGiveItemToAllPlayersOnline(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::MetricsConfigure(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::DisableZone(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::InitDonationAmount(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::KillServersCountdown(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::DisableFAQ(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ThrottleQueue(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::GateGMAccess(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ReconnectCrisp(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ModerateKickAccount(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ToggleCrispServer(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::QuickDrainServer(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::QuickDrainServerRenew(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ReplicateCharacter(HTTPReply& reply, const json& data) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::GetServerStatus(HTTPReply& reply) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
|
void CSRCommandHandler::ReloadServerINIs(HTTPReply& reply) {
|
||||||
|
reply.status = eHTTPStatusCode::NOT_IMPLEMENTED;
|
||||||
|
reply.message = "{\"error\":\"Not Implemented\"}";
|
||||||
|
}
|
||||||
62
dChatServer/CSRCommandHandler.h
Normal file
62
dChatServer/CSRCommandHandler.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef __CSR_COMMAND_HANDLER__H__
|
||||||
|
#define __CSR_COMMAND_HANDLER__H__
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include "json_fwd.hpp"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
struct HTTPReply;
|
||||||
|
|
||||||
|
|
||||||
|
namespace CSRCommandHandler {
|
||||||
|
void HandleCSRCommand(HTTPReply& reply, const json& data);
|
||||||
|
|
||||||
|
void QueryServerStatus(HTTPReply& reply, const json& data);
|
||||||
|
void QueryCharacterLocation(HTTPReply& reply, const json& data);
|
||||||
|
void QueryCharacterOnlineStatus(HTTPReply& reply, const json& data);
|
||||||
|
void InventoryAddItem(HTTPReply& reply, const json& data);
|
||||||
|
void InventoryDeleteItem(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateMuteAccount(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateBanAccount(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateEducateCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateKickCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateWarnCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateRenameCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateDeleteCharacterFriend(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateKillCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterHealth(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterArmor(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterImagination(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterMaxHealth(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterMaxArmor(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterMaxImagination(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterCurrency(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterReputation(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterLegoScore(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterEmotes(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterAddAchievement(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterCompleteAchievement(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterRemoveAchievement(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterPositionOffline(HTTPReply& reply, const json& data);
|
||||||
|
void UpdateCharacterInvSlotAmount(HTTPReply& reply, const json& data);
|
||||||
|
void UtilitySaveCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void UtilitySendMail(HTTPReply& reply, const json& data);
|
||||||
|
void UtilityGiveItemToAllPlayersOnline(HTTPReply& reply, const json& data);
|
||||||
|
void MetricsConfigure(HTTPReply& reply, const json& data);
|
||||||
|
void DisableZone(HTTPReply& reply, const json& data);
|
||||||
|
void InitDonationAmount(HTTPReply& reply, const json& data);
|
||||||
|
void KillServersCountdown(HTTPReply& reply, const json& data);
|
||||||
|
void DisableFAQ(HTTPReply& reply, const json& data);
|
||||||
|
void ThrottleQueue(HTTPReply& reply, const json& data);
|
||||||
|
void GateGMAccess(HTTPReply& reply, const json& data);
|
||||||
|
void ReconnectCrisp(HTTPReply& reply, const json& data);
|
||||||
|
void ModerateKickAccount(HTTPReply& reply, const json& data);
|
||||||
|
void ToggleCrispServer(HTTPReply& reply, const json& data);
|
||||||
|
void QuickDrainServer(HTTPReply& reply, const json& data);
|
||||||
|
void QuickDrainServerRenew(HTTPReply& reply, const json& data);
|
||||||
|
void ReplicateCharacter(HTTPReply& reply, const json& data);
|
||||||
|
void GetServerStatus(HTTPReply& reply);
|
||||||
|
void ReloadServerINIs(HTTPReply& reply);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !__CSR_COMMAND_HANDLER__H__
|
||||||
@@ -29,6 +29,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
auto& player = Game::playerContainer.GetPlayerDataMutable(playerID);
|
auto& player = Game::playerContainer.GetPlayerDataMutable(playerID);
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
|
if (player.friends.empty()) {
|
||||||
auto friendsList = Database::Get()->GetFriendsList(playerID);
|
auto friendsList = Database::Get()->GetFriendsList(playerID);
|
||||||
for (const auto& friendData : friendsList) {
|
for (const auto& friendData : friendsList) {
|
||||||
FriendData fd;
|
FriendData fd;
|
||||||
@@ -49,7 +50,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
fd.zoneID = fr.zoneID;
|
fd.zoneID = fr.zoneID;
|
||||||
|
|
||||||
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
//Since this friend is online, we need to update them on the fact that we've just logged in:
|
||||||
if (player.isLogin) SendFriendUpdate(fr, player, 1, fd.isBestFriend);
|
SendFriendUpdate(fr, player, 1, fd.isBestFriend);
|
||||||
} else {
|
} else {
|
||||||
fd.isOnline = false;
|
fd.isOnline = false;
|
||||||
fd.zoneID = LWOZONEID();
|
fd.zoneID = LWOZONEID();
|
||||||
@@ -57,6 +58,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
player.friends.push_back(fd);
|
player.friends.push_back(fd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
@@ -103,8 +105,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Intentional copy
|
auto& requestee = Game::playerContainer.GetPlayerDataMutable(playerName);
|
||||||
PlayerData requestee = Game::playerContainer.GetPlayerData(playerName);
|
|
||||||
|
|
||||||
// Check if player is online first
|
// Check if player is online first
|
||||||
if (isBestFriendRequest && !requestee) {
|
if (isBestFriendRequest && !requestee) {
|
||||||
@@ -189,25 +190,20 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee.playerID, bestFriendStatus);
|
Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee.playerID, bestFriendStatus);
|
||||||
// Sent the best friend update here if the value is 3
|
// Sent the best friend update here if the value is 3
|
||||||
if (bestFriendStatus == 3U) {
|
if (bestFriendStatus == 3U) {
|
||||||
|
requestee.countOfBestFriends += 1;
|
||||||
|
requestor.countOfBestFriends += 1;
|
||||||
if (requestee.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee, requestor, eAddFriendResponseType::ACCEPTED, false, true);
|
if (requestee.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee, requestor, eAddFriendResponseType::ACCEPTED, false, true);
|
||||||
if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::ACCEPTED, false, true);
|
if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::ACCEPTED, false, true);
|
||||||
|
|
||||||
for (auto& friendData : requestor.friends) {
|
for (auto& friendData : requestor.friends) {
|
||||||
if (friendData.friendID == requestee.playerID) {
|
if (friendData.friendID == requestee.playerID) {
|
||||||
friendData.isBestFriend = true;
|
friendData.isBestFriend = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestor.countOfBestFriends += 1;
|
for (auto& friendData : requestee.friends) {
|
||||||
|
|
||||||
auto& toModify = Game::playerContainer.GetPlayerDataMutable(playerName);
|
|
||||||
if (toModify) {
|
|
||||||
for (auto& friendData : toModify.friends) {
|
|
||||||
if (friendData.friendID == requestor.playerID) {
|
if (friendData.friendID == requestor.playerID) {
|
||||||
friendData.isBestFriend = true;
|
friendData.isBestFriend = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toModify.countOfBestFriends += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ int main(int argc, char** argv) {
|
|||||||
Game::assetManager = new AssetManager(clientPath);
|
Game::assetManager = new AssetManager(clientPath);
|
||||||
} catch (std::runtime_error& ex) {
|
} catch (std::runtime_error& ex) {
|
||||||
LOG("Got an error while setting up assets: %s", ex.what());
|
LOG("Got an error while setting up assets: %s", ex.what());
|
||||||
delete Game::logger;
|
|
||||||
delete Game::config;
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,32 +86,18 @@ int main(int argc, char** argv) {
|
|||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
LOG("Got an error while connecting to the database: %s", ex.what());
|
LOG("Got an error while connecting to the database: %s", ex.what());
|
||||||
Database::Destroy("ChatServer");
|
Database::Destroy("ChatServer");
|
||||||
|
delete Game::server;
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
delete Game::config;
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// seyup the chat api web server
|
|
||||||
bool web_server_enabled = Game::config->GetValue("web_server_enabled") == "1";
|
|
||||||
ChatWebAPI chatwebapi;
|
|
||||||
if (web_server_enabled && !chatwebapi.Startup()){
|
|
||||||
// if we want the web api and it fails to start, exit
|
|
||||||
LOG("Failed to start web server, shutting down.");
|
|
||||||
Database::Destroy("ChatServer");
|
|
||||||
delete Game::logger;
|
|
||||||
delete Game::config;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP;
|
std::string masterIP;
|
||||||
uint32_t masterPort = 1000;
|
uint32_t masterPort = 1000;
|
||||||
std::string masterPassword;
|
|
||||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
if (masterInfo) {
|
if (masterInfo) {
|
||||||
masterIP = masterInfo->ip;
|
masterIP = masterInfo->ip;
|
||||||
masterPort = masterInfo->port;
|
masterPort = masterInfo->port;
|
||||||
masterPassword = masterInfo->password;
|
|
||||||
}
|
}
|
||||||
//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.
|
||||||
std::string ourIP = "localhost";
|
std::string ourIP = "localhost";
|
||||||
@@ -121,7 +106,7 @@ int main(int argc, char** argv) {
|
|||||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||||
|
|
||||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal, masterPassword);
|
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
|
||||||
|
|
||||||
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||||
@@ -139,6 +124,11 @@ int main(int argc, char** argv) {
|
|||||||
uint32_t framesSinceMasterDisconnect = 0;
|
uint32_t framesSinceMasterDisconnect = 0;
|
||||||
uint32_t framesSinceLastSQLPing = 0;
|
uint32_t framesSinceLastSQLPing = 0;
|
||||||
|
|
||||||
|
|
||||||
|
bool web_server_enabled = Game::config->GetValue("web_server_enabled") == "1";
|
||||||
|
ChatWebAPI chatwebapi;
|
||||||
|
if (web_server_enabled) chatwebapi.Listen();
|
||||||
|
|
||||||
auto lastTime = std::chrono::high_resolution_clock::now();
|
auto lastTime = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
Game::logger->Flush(); // once immediately before main loop
|
Game::logger->Flush(); // once immediately before main loop
|
||||||
|
|||||||
@@ -8,13 +8,15 @@
|
|||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "JSONUtils.h"
|
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
#include "JSONUtils.h"
|
||||||
#include "eHTTPMethod.h"
|
#include "eHTTPMethod.h"
|
||||||
|
#include "eHTTPStatusCode.h"
|
||||||
#include "magic_enum.hpp"
|
#include "magic_enum.hpp"
|
||||||
#include "ChatPackets.h"
|
#include "ChatPackets.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
#include "Database.h"
|
#include "eCSRCommand.h"
|
||||||
|
#include "CSRCommandHandler.h"
|
||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_WIN32
|
#ifdef DARKFLAME_PLATFORM_WIN32
|
||||||
#pragma push_macro("DELETE")
|
#pragma push_macro("DELETE")
|
||||||
@@ -27,41 +29,44 @@ typedef struct mg_connection mg_connection;
|
|||||||
typedef struct mg_http_message mg_http_message;
|
typedef struct mg_http_message mg_http_message;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
const std::string root_path = "/api/v1/";
|
||||||
const char* json_content_type = "Content-Type: application/json\r\n";
|
const char* json_content_type = "Content-Type: application/json\r\n";
|
||||||
std::map<std::pair<eHTTPMethod, std::string>, WebAPIHTTPRoute> Routes {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValidateAuthentication(const mg_http_message* http_msg) {
|
void HandlePlayersRequest(HTTPReply& reply) {
|
||||||
// TO DO: This is just a placeholder for now
|
|
||||||
// use tokens or something at a later point if we want to implement authentication
|
|
||||||
// bit using the listen bind address to limit external access is good enough to start with
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValidateJSON(std::optional<json> data, HTTPReply& reply) {
|
|
||||||
if (!data) {
|
|
||||||
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
|
||||||
reply.message = "{\"error\":\"Invalid JSON\"}";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandlePlayersRequest(HTTPReply& reply, std::string body) {
|
|
||||||
const json data = Game::playerContainer;
|
const json data = Game::playerContainer;
|
||||||
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
|
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
|
||||||
reply.message = data.empty() ? "{\"error\":\"No Players Online\"}" : data.dump();
|
reply.message = data.empty() ? "{\"error\":\"No Players Online\"}" : data.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleTeamsRequest(HTTPReply& reply, std::string body) {
|
void HandleTeamsRequest(HTTPReply& reply) {
|
||||||
const json data = Game::playerContainer.GetTeamContainer();
|
const json data = Game::playerContainer.GetTeamContainer();
|
||||||
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
|
reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK;
|
||||||
reply.message = data.empty() ? "{\"error\":\"No Teams Online\"}" : data.dump();
|
reply.message = data.empty() ? "{\"error\":\"No Teams Online\"}" : data.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleAnnounceRequest(HTTPReply& reply, std::string body) {
|
void HandleInvalidRoute(HTTPReply& reply) {
|
||||||
auto data = GeneralUtils::TryParse<json>(body);
|
reply.status = eHTTPStatusCode::NOT_FOUND;
|
||||||
if (!ValidateJSON(data, reply)) return;
|
reply.message = "{\"error\":\"Invalid Route\"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleGET(HTTPReply& reply, const ChatWebAPI::eRoute& route , const std::string& body) {
|
||||||
|
switch (route) {
|
||||||
|
case ChatWebAPI::eRoute::PLAYERS:
|
||||||
|
HandlePlayersRequest(reply);
|
||||||
|
break;
|
||||||
|
case ChatWebAPI::eRoute::TEAMS:
|
||||||
|
HandleTeamsRequest(reply);
|
||||||
|
break;
|
||||||
|
case ChatWebAPI::eRoute::INVALID:
|
||||||
|
default:
|
||||||
|
HandleInvalidRoute(reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleAnnounceRequest(HTTPReply& reply, const std::optional<json>& data) {
|
||||||
|
if (!JSONUtils::Validate(data, reply)) return;
|
||||||
|
|
||||||
const auto& good_data = data.value();
|
const auto& good_data = data.value();
|
||||||
auto check = JSONUtils::CheckRequiredData(good_data, { "title", "message" });
|
auto check = JSONUtils::CheckRequiredData(good_data, { "title", "message" });
|
||||||
@@ -80,9 +85,33 @@ void HandleAnnounceRequest(HTTPReply& reply, std::string body) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleInvalidRoute(HTTPReply& reply) {
|
void HandleCSRCommandRequest(HTTPReply& reply, const std::optional<json>& data) {
|
||||||
reply.status = eHTTPStatusCode::NOT_FOUND;
|
if (!JSONUtils::Validate(data, reply)) return;
|
||||||
reply.message = "{\"error\":\"Invalid Route\"}";
|
|
||||||
|
const auto& good_data = data.value();
|
||||||
|
auto check = JSONUtils::CheckRequiredData(good_data, { "command" });
|
||||||
|
if (!check.empty()) {
|
||||||
|
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
||||||
|
reply.message = check;
|
||||||
|
} else {
|
||||||
|
CSRCommandHandler::HandleCSRCommand(reply, good_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandlePOST(HTTPReply& reply, const ChatWebAPI::eRoute& route , const std::string& body) {
|
||||||
|
auto data = GeneralUtils::TryParse<json>(body);
|
||||||
|
switch (route) {
|
||||||
|
case ChatWebAPI::eRoute::ANNOUNCE:
|
||||||
|
HandleAnnounceRequest(reply, data.value());
|
||||||
|
break;
|
||||||
|
case ChatWebAPI::eRoute::CSR:
|
||||||
|
HandleCSRCommandRequest(reply, data.value());
|
||||||
|
break;
|
||||||
|
case ChatWebAPI::eRoute::INVALID:
|
||||||
|
default:
|
||||||
|
HandleInvalidRoute(reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleHTTPMessage(mg_connection* connection, const mg_http_message* http_msg) {
|
void HandleHTTPMessage(mg_connection* connection, const mg_http_message* http_msg) {
|
||||||
@@ -91,7 +120,7 @@ void HandleHTTPMessage(mg_connection* connection, const mg_http_message* http_ms
|
|||||||
if (!http_msg) {
|
if (!http_msg) {
|
||||||
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
||||||
reply.message = "{\"error\":\"Invalid Request\"}";
|
reply.message = "{\"error\":\"Invalid Request\"}";
|
||||||
} else if (ValidateAuthentication(http_msg)) {
|
} else {
|
||||||
|
|
||||||
// convert method from cstring to std string
|
// convert method from cstring to std string
|
||||||
std::string method_string(http_msg->method.buf, http_msg->method.len);
|
std::string method_string(http_msg->method.buf, http_msg->method.len);
|
||||||
@@ -100,21 +129,38 @@ void HandleHTTPMessage(mg_connection* connection, const mg_http_message* http_ms
|
|||||||
|
|
||||||
// convert uri from cstring to std string
|
// convert uri from cstring to std string
|
||||||
std::string uri(http_msg->uri.buf, http_msg->uri.len);
|
std::string uri(http_msg->uri.buf, http_msg->uri.len);
|
||||||
std::transform(uri.begin(), uri.end(), uri.begin(), ::tolower);
|
// check for root path
|
||||||
|
if (uri.find(root_path) == 0) {
|
||||||
|
// remove root path from uri
|
||||||
|
uri.erase(0, root_path.length());
|
||||||
|
// convert uri to uppercase
|
||||||
|
std::transform(uri.begin(), uri.end(), uri.begin(), ::toupper);
|
||||||
|
// convert uri string to route enum
|
||||||
|
ChatWebAPI::eRoute route = magic_enum::enum_cast<ChatWebAPI::eRoute>(uri).value_or(ChatWebAPI::eRoute::INVALID);
|
||||||
// convert body from cstring to std string
|
// convert body from cstring to std string
|
||||||
std::string body(http_msg->body.buf, http_msg->body.len);
|
std::string body(http_msg->body.buf, http_msg->body.len);
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
const auto routeItr = Routes.find({method, uri});
|
case eHTTPMethod::GET:
|
||||||
|
HandleGET(reply, route, body);
|
||||||
if (routeItr != Routes.end()) {
|
break;
|
||||||
const auto& [_, route] = *routeItr;
|
case eHTTPMethod::POST:
|
||||||
route.handle(reply, body);
|
HandlePOST(reply, route, body);
|
||||||
} else HandleInvalidRoute(reply);
|
break;
|
||||||
} else {
|
case eHTTPMethod::PUT:
|
||||||
reply.status = eHTTPStatusCode::UNAUTHORIZED;
|
case eHTTPMethod::DELETE:
|
||||||
reply.message = "{\"error\":\"Unauthorized\"}";
|
case eHTTPMethod::HEAD:
|
||||||
|
case eHTTPMethod::CONNECT:
|
||||||
|
case eHTTPMethod::OPTIONS:
|
||||||
|
case eHTTPMethod::TRACE:
|
||||||
|
case eHTTPMethod::PATCH:
|
||||||
|
case eHTTPMethod::INVALID:
|
||||||
|
default:
|
||||||
|
reply.status = eHTTPStatusCode::METHOD_NOT_ALLOWED;
|
||||||
|
reply.message = "{\"error\":\"Invalid Method\"}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mg_http_reply(connection, static_cast<int>(reply.status), json_content_type, reply.message.c_str());
|
mg_http_reply(connection, static_cast<int>(reply.status), json_content_type, reply.message.c_str());
|
||||||
}
|
}
|
||||||
@@ -130,14 +176,9 @@ void HandleRequests(mg_connection* connection, int request, void* request_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWebAPI::RegisterHTTPRoutes(WebAPIHTTPRoute route) {
|
#ifdef DARKFLAME_PLATFORM_WIN32
|
||||||
auto [_, success] = Routes.try_emplace({ route.method, route.path }, route);
|
#pragma pop_macro("DELETE")
|
||||||
if (!success) {
|
#endif
|
||||||
LOG_DEBUG("Failed to register route %s", route.path.c_str());
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG("Registered route %s", route.path.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatWebAPI::ChatWebAPI() {
|
ChatWebAPI::ChatWebAPI() {
|
||||||
mg_log_set(MG_LL_NONE);
|
mg_log_set(MG_LL_NONE);
|
||||||
@@ -148,8 +189,8 @@ ChatWebAPI::~ChatWebAPI() {
|
|||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatWebAPI::Startup() {
|
void ChatWebAPI::Listen() {
|
||||||
// Make listen address
|
// make listen address
|
||||||
std::string listen_ip = Game::config->GetValue("web_server_listen_ip");
|
std::string listen_ip = Game::config->GetValue("web_server_listen_ip");
|
||||||
if (listen_ip == "localhost") listen_ip = "127.0.0.1";
|
if (listen_ip == "localhost") listen_ip = "127.0.0.1";
|
||||||
|
|
||||||
@@ -159,38 +200,10 @@ bool ChatWebAPI::Startup() {
|
|||||||
|
|
||||||
// Create HTTP listener
|
// Create HTTP listener
|
||||||
if (!mg_http_listen(&mgr, listen_address.c_str(), HandleRequests, NULL)) {
|
if (!mg_http_listen(&mgr, listen_address.c_str(), HandleRequests, NULL)) {
|
||||||
LOG("Failed to create web server listener on %s", listen_port.c_str());
|
LOG("Failed to create web server listener");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register routes
|
|
||||||
|
|
||||||
// API v1 routes
|
|
||||||
std::string v1_route = "/api/v1/";
|
|
||||||
RegisterHTTPRoutes({
|
|
||||||
.path = v1_route + "players",
|
|
||||||
.method = eHTTPMethod::GET,
|
|
||||||
.handle = HandlePlayersRequest
|
|
||||||
});
|
|
||||||
|
|
||||||
RegisterHTTPRoutes({
|
|
||||||
.path = v1_route + "teams",
|
|
||||||
.method = eHTTPMethod::GET,
|
|
||||||
.handle = HandleTeamsRequest
|
|
||||||
});
|
|
||||||
|
|
||||||
RegisterHTTPRoutes({
|
|
||||||
.path = v1_route + "announce",
|
|
||||||
.method = eHTTPMethod::POST,
|
|
||||||
.handle = HandleAnnounceRequest
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatWebAPI::ReceiveRequests() {
|
void ChatWebAPI::ReceiveRequests() {
|
||||||
mg_mgr_poll(&mgr, 15);
|
mg_mgr_poll(&mgr, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_WIN32
|
|
||||||
#pragma pop_macro("DELETE")
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,36 +1,30 @@
|
|||||||
#ifndef __CHATWEBAPI_H__
|
#ifndef CHATWEBAPI_H
|
||||||
#define __CHATWEBAPI_H__
|
#define CHATWEBAPI_H
|
||||||
#include <string>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
#include "eHTTPStatusCode.h"
|
|
||||||
|
|
||||||
enum class eHTTPMethod;
|
|
||||||
|
|
||||||
typedef struct mg_mgr mg_mgr;
|
typedef struct mg_mgr mg_mgr;
|
||||||
|
|
||||||
struct HTTPReply {
|
|
||||||
eHTTPStatusCode status = eHTTPStatusCode::NOT_FOUND;
|
|
||||||
std::string message = "{\"error\":\"Not Found\"}";
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WebAPIHTTPRoute {
|
|
||||||
std::string path;
|
|
||||||
eHTTPMethod method;
|
|
||||||
std::function<void(HTTPReply&, const std::string&)> handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChatWebAPI {
|
class ChatWebAPI {
|
||||||
public:
|
public:
|
||||||
ChatWebAPI();
|
ChatWebAPI();
|
||||||
~ChatWebAPI();
|
~ChatWebAPI();
|
||||||
void ReceiveRequests();
|
void ReceiveRequests();
|
||||||
void RegisterHTTPRoutes(WebAPIHTTPRoute route);
|
void Listen();
|
||||||
bool Startup();
|
enum class eRoute {
|
||||||
|
// GET
|
||||||
|
PLAYERS,
|
||||||
|
TEAMS,
|
||||||
|
// POST
|
||||||
|
ANNOUNCE,
|
||||||
|
CSR,
|
||||||
|
// INVALID
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
mg_mgr mgr;
|
mg_mgr mgr;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CHATWEBAPI_H__
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "JSONUtils.h"
|
#include "JSONUtils.h"
|
||||||
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
|
#include "eHTTPStatusCode.h"
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
@@ -17,11 +18,7 @@ void to_json(json& data, const PlayerData& playerData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void to_json(json& data, const PlayerContainer& playerContainer) {
|
void to_json(json& data, const PlayerContainer& playerContainer) {
|
||||||
data = json::array();
|
data = playerContainer.GetAllPlayers();
|
||||||
for(auto& playerData : playerContainer.GetAllPlayers()) {
|
|
||||||
if (playerData.first == LWOOBJID_EMPTY) continue;
|
|
||||||
data.push_back(playerData.second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void to_json(json& data, const TeamContainer& teamContainer) {
|
void to_json(json& data, const TeamContainer& teamContainer) {
|
||||||
@@ -60,3 +57,12 @@ std::string JSONUtils::CheckRequiredData(const json& data, const std::vector<std
|
|||||||
}
|
}
|
||||||
return check["error"].empty() ? "" : check.dump();
|
return check["error"].empty() ? "" : check.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JSONUtils::Validate(const std::optional<json>& data, HTTPReply& reply) {
|
||||||
|
if (!data) {
|
||||||
|
reply.status = eHTTPStatusCode::BAD_REQUEST;
|
||||||
|
reply.message = "{\"error\":\"Invalid JSON\"}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
#include "json_fwd.hpp"
|
#include "json_fwd.hpp"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
|
#include "eHTTPStatusCode.h"
|
||||||
|
|
||||||
|
struct HTTPReply {
|
||||||
|
eHTTPStatusCode status = eHTTPStatusCode::NOT_FOUND;
|
||||||
|
std::string message = "{\"error\":\"Not Found\"}";
|
||||||
|
};
|
||||||
|
|
||||||
void to_json(nlohmann::json& data, const PlayerData& playerData);
|
void to_json(nlohmann::json& data, const PlayerData& playerData);
|
||||||
void to_json(nlohmann::json& data, const PlayerContainer& playerContainer);
|
void to_json(nlohmann::json& data, const PlayerContainer& playerContainer);
|
||||||
@@ -12,6 +18,7 @@ void to_json(nlohmann::json& data, const TeamData& teamData);
|
|||||||
namespace JSONUtils {
|
namespace JSONUtils {
|
||||||
// check required data for reqeust
|
// check required data for reqeust
|
||||||
std::string CheckRequiredData(const nlohmann::json& data, const std::vector<std::string>& requiredData);
|
std::string CheckRequiredData(const nlohmann::json& data, const std::vector<std::string>& requiredData);
|
||||||
|
bool Validate(const std::optional<nlohmann::json>& data, HTTPReply& reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __JSONUTILS_H__
|
#endif // __JSONUTILS_H__
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isLogin = !m_Players.contains(playerId);
|
|
||||||
auto& data = m_Players[playerId];
|
auto& data = m_Players[playerId];
|
||||||
data = PlayerData();
|
|
||||||
data.isLogin = isLogin;
|
|
||||||
data.playerID = playerId;
|
data.playerID = playerId;
|
||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ struct PlayerData {
|
|||||||
std::vector<IgnoreData> ignoredPlayers;
|
std::vector<IgnoreData> ignoredPlayers;
|
||||||
eGameMasterLevel gmLevel = static_cast<eGameMasterLevel>(0); // CIVILLIAN
|
eGameMasterLevel gmLevel = static_cast<eGameMasterLevel>(0); // CIVILLIAN
|
||||||
bool isFTP = false;
|
bool isFTP = false;
|
||||||
bool isLogin = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -98,8 +97,8 @@ public:
|
|||||||
LWOOBJID GetId(const std::u16string& playerName);
|
LWOOBJID GetId(const std::u16string& playerName);
|
||||||
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
|
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
|
||||||
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
|
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
|
||||||
const TeamContainer& GetTeamContainer() { return m_TeamContainer; }
|
const TeamContainer& GetTeamContainer() { return teamContainer; }
|
||||||
std::vector<TeamData*>& GetTeamsMut() { return m_TeamContainer.mTeams; };
|
std::vector<TeamData*>& GetTeamsMut() { return teamContainer.mTeams; };
|
||||||
const std::vector<TeamData*>& GetTeams() { return GetTeamsMut(); };
|
const std::vector<TeamData*>& GetTeams() { return GetTeamsMut(); };
|
||||||
|
|
||||||
void Update(const float deltaTime);
|
void Update(const float deltaTime);
|
||||||
@@ -108,7 +107,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
LWOOBJID m_TeamIDCounter = 0;
|
LWOOBJID m_TeamIDCounter = 0;
|
||||||
std::map<LWOOBJID, PlayerData> m_Players;
|
std::map<LWOOBJID, PlayerData> m_Players;
|
||||||
TeamContainer m_TeamContainer{};
|
TeamContainer teamContainer{};
|
||||||
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
||||||
std::map<LWOOBJID, float> m_PlayersToRemove;
|
std::map<LWOOBJID, float> m_PlayersToRemove;
|
||||||
uint32_t m_MaxNumberOfBestFriends = 5;
|
uint32_t m_MaxNumberOfBestFriends = 5;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -40,7 +39,6 @@ public:
|
|||||||
// AMFValue template class instantiations
|
// AMFValue template class instantiations
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
class AMFValue : public AMFBaseValue {
|
class AMFValue : public AMFBaseValue {
|
||||||
static_assert(!std::is_same_v<ValueType, std::string_view>, "AMFValue cannot be instantiated with std::string_view");
|
|
||||||
public:
|
public:
|
||||||
AMFValue() = default;
|
AMFValue() = default;
|
||||||
AMFValue(const ValueType value) : m_Data{ value } {}
|
AMFValue(const ValueType value) : m_Data{ value } {}
|
||||||
@@ -53,15 +51,6 @@ public:
|
|||||||
|
|
||||||
void SetValue(const ValueType value) { m_Data = value; }
|
void SetValue(const ValueType value) { m_Data = value; }
|
||||||
|
|
||||||
AMFValue<ValueType>& operator=(const AMFValue<ValueType>& other) {
|
|
||||||
return operator=(other.m_Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFValue<ValueType>& operator=(const ValueType& other) {
|
|
||||||
m_Data = other;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ValueType m_Data;
|
ValueType m_Data;
|
||||||
};
|
};
|
||||||
@@ -221,17 +210,13 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
template<typename AmfType>
|
void Insert(const std::string_view key, std::unique_ptr<AMFBaseValue> value) {
|
||||||
AmfType& Insert(const std::string_view key, std::unique_ptr<AmfType> value) {
|
|
||||||
const auto element = m_Associative.find(key);
|
const auto element = m_Associative.find(key);
|
||||||
auto& toReturn = *value;
|
|
||||||
if (element != m_Associative.cend() && element->second) {
|
if (element != m_Associative.cend() && element->second) {
|
||||||
element->second = std::move(value);
|
element->second = std::move(value);
|
||||||
} else {
|
} else {
|
||||||
m_Associative.emplace(key, std::move(value));
|
m_Associative.emplace(key, std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,15 +228,11 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
template<typename AmfType>
|
void Insert(const size_t index, std::unique_ptr<AMFBaseValue> value) {
|
||||||
AmfType& Insert(const size_t index, std::unique_ptr<AmfType> value) {
|
|
||||||
auto& toReturn = *value;
|
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= m_Dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
m_Dense.resize(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Dense.at(index) = std::move(value);
|
m_Dense.at(index) = std::move(value);
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,10 +257,10 @@ public:
|
|||||||
*
|
*
|
||||||
* @param key The key to remove from the associative portion
|
* @param key The key to remove from the associative portion
|
||||||
*/
|
*/
|
||||||
void Remove(const std::string& key) {
|
void Remove(const std::string& key, const bool deleteValue = true) {
|
||||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||||
if (it != m_Associative.cend()) {
|
if (it != m_Associative.cend()) {
|
||||||
m_Associative.erase(it);
|
if (deleteValue) m_Associative.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,18 +343,6 @@ public:
|
|||||||
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() {
|
|
||||||
m_Associative.clear();
|
|
||||||
m_Dense.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename AmfType = AMFArrayValue>
|
|
||||||
AmfType& PushDebug(const std::string_view name) {
|
|
||||||
auto* value = PushArray();
|
|
||||||
value->Insert("name", name.data());
|
|
||||||
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
|
|||||||
54
dCommon/dEnums/eCSRCommand.h
Normal file
54
dCommon/dEnums/eCSRCommand.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef __ECSRCOMMAND__H__
|
||||||
|
#define __ECSRCOMMAND__H__
|
||||||
|
|
||||||
|
enum class eCSRCommand {
|
||||||
|
QUERY_SERVER_STATUS,
|
||||||
|
QUERY_CHARACTER_LOCATION,
|
||||||
|
QUERY_CHARACTER_ONLINE_STATUS,
|
||||||
|
INVENTORY_ADD_ITEM,
|
||||||
|
INVENTORY_DELETE_ITEM,
|
||||||
|
MODERATE_MUTE_ACCOUNT,
|
||||||
|
MODERATE_BAN_ACCOUNT,
|
||||||
|
MODERATE_EDUCATE_CHARACTER,
|
||||||
|
MODERATE_KICK_CHARACTER,
|
||||||
|
MODERATE_WARN_CHARACTER,
|
||||||
|
MODERATE_RENAME_CHARACTER,
|
||||||
|
MODERATE_DELETE_CHARACTER_FRIEND,
|
||||||
|
MODERATE_KILL_CHARACTER,
|
||||||
|
UPDATE_CHARACTER_HEALTH,
|
||||||
|
UPDATE_CHARACTER_ARMOR,
|
||||||
|
UPDATE_CHARACTER_IMAGINATION,
|
||||||
|
UPDATE_CHARACTER_MAX_HEALTH,
|
||||||
|
UPDATE_CHARACTER_MAX_ARMOR,
|
||||||
|
UPDATE_CHARACTER_MAX_IMAGINATION,
|
||||||
|
UPDATE_CHARACTER_CURRENCY,
|
||||||
|
UPDATE_CHARACTER_REPUTATION,
|
||||||
|
UPDATE_CHARACTER_LEGO_SCORE,
|
||||||
|
UPDATE_CHARACTER_EMOTES,
|
||||||
|
UPDATE_CHARACTER_ADD_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_COMPLETE_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_REMOVE_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_POSITION_OFFLINE,
|
||||||
|
UPDATE_CHARACTER_INV_SLOT_AMOUNT,
|
||||||
|
UTILITY_SAVE_CHARACTER,
|
||||||
|
UTILITY_SEND_MAIL,
|
||||||
|
UTILITY_GIVE_ITEM_TO_ALL_PLAYERS_ONLINE,
|
||||||
|
METRICS_CONFIGURE,
|
||||||
|
DISABLE_ZONE,
|
||||||
|
INIT_DONATION_AMOUNT,
|
||||||
|
KILL_SERVERS_COUNTDOWN,
|
||||||
|
DISABLE_FAQ,
|
||||||
|
THROTTLEQUEUE,
|
||||||
|
GATEGM_ACCESS,
|
||||||
|
RECONNECT_CRISP,
|
||||||
|
MODERATE_KICK_ACCOUNT,
|
||||||
|
TOGGLE_CRISP_SERVER,
|
||||||
|
QUICK_DRAIN_SERVER,
|
||||||
|
QUICK_DRAIN_SERVER_RENEW,
|
||||||
|
REPLICATE_CHARACTER,
|
||||||
|
GET_SERVER_STATUS,
|
||||||
|
RELOAD_SERVER_INIS,
|
||||||
|
INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !__ECSRCOMMAND__H__
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#include "CDPlayerFlagsTable.h"
|
|
||||||
|
|
||||||
#include "CDClientDatabase.h"
|
|
||||||
|
|
||||||
namespace CDPlayerFlagsTable {
|
|
||||||
Table entries;
|
|
||||||
|
|
||||||
void ReadEntry(CppSQLite3Query& table) {
|
|
||||||
Entry entry;
|
|
||||||
entry.sessionOnly = table.getIntField("SessionOnly") == 1;
|
|
||||||
entry.onlySetByServer = table.getIntField("OnlySetByServer") == 1;
|
|
||||||
entry.sessionZoneOnly = table.getIntField("SessionZoneOnly") == 1;
|
|
||||||
entries[table.getIntField("id")] = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadValuesFromDatabase() {
|
|
||||||
auto table = CDClientDatabase::ExecuteQuery("SELECT * FROM PlayerFlags;");
|
|
||||||
|
|
||||||
if (!table.eof()) {
|
|
||||||
do {
|
|
||||||
ReadEntry(table);
|
|
||||||
} while (!table.nextRow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::optional<Entry> GetEntry(const FlagId flagId) {
|
|
||||||
if (!entries.contains(flagId)) {
|
|
||||||
auto table = CDClientDatabase::CreatePreppedStmt("SELECT * FROM PlayerFlags WHERE id = ?;");
|
|
||||||
table.bind(1, static_cast<int>(flagId));
|
|
||||||
auto result = table.execQuery();
|
|
||||||
if (!result.eof()) {
|
|
||||||
ReadEntry(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries[flagId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef CDPLAYERFLAGSTABLE_H
|
|
||||||
#define CDPLAYERFLAGSTABLE_H
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace CDPlayerFlagsTable {
|
|
||||||
struct Entry {
|
|
||||||
bool sessionOnly{};
|
|
||||||
bool onlySetByServer{};
|
|
||||||
bool sessionZoneOnly{};
|
|
||||||
};
|
|
||||||
|
|
||||||
using FlagId = uint32_t;
|
|
||||||
using Table = std::map<FlagId, std::optional<Entry>>;
|
|
||||||
|
|
||||||
void LoadValuesFromDatabase();
|
|
||||||
const std::optional<Entry> GetEntry(const FlagId flagId);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!CDPLAYERFLAGSTABLE_H
|
|
||||||
@@ -25,7 +25,6 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
|||||||
"CDObjectsTable.cpp"
|
"CDObjectsTable.cpp"
|
||||||
"CDPetComponentTable.cpp"
|
"CDPetComponentTable.cpp"
|
||||||
"CDPackageComponentTable.cpp"
|
"CDPackageComponentTable.cpp"
|
||||||
"CDPlayerFlagsTable.cpp"
|
|
||||||
"CDPhysicsComponentTable.cpp"
|
"CDPhysicsComponentTable.cpp"
|
||||||
"CDPropertyEntranceComponentTable.cpp"
|
"CDPropertyEntranceComponentTable.cpp"
|
||||||
"CDPropertyTemplateTable.cpp"
|
"CDPropertyTemplateTable.cpp"
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ public:
|
|||||||
struct MasterInfo {
|
struct MasterInfo {
|
||||||
std::string ip;
|
std::string ip;
|
||||||
uint32_t port{};
|
uint32_t port{};
|
||||||
std::string password{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the master server ip and port.
|
// Set the master server ip and port.
|
||||||
virtual void SetMasterInfo(const MasterInfo& info) = 0;
|
virtual void SetMasterIp(const std::string_view ip, const uint32_t port) = 0;
|
||||||
|
|
||||||
// Get the master server info.
|
// Get the master server info.
|
||||||
virtual std::optional<MasterInfo> GetMasterInfo() = 0;
|
virtual std::optional<MasterInfo> GetMasterInfo() = 0;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
void UpdatePersistentId(const uint32_t id) override;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "MySQLDatabase.h"
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
void MySQLDatabase::SetMasterInfo(const MasterInfo& info) {
|
void MySQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||||
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||||
// since it would be two queries anyways.
|
// since it would be two queries anyways.
|
||||||
ExecuteDelete("TRUNCATE TABLE servers;");
|
ExecuteDelete("TRUNCATE TABLE servers;");
|
||||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`, `master_password`) VALUES ('master', ?, ?, 0, 171022, ?)", info.ip, info.port, info.password);
|
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IServers::MasterInfo> MySQLDatabase::GetMasterInfo() {
|
std::optional<IServers::MasterInfo> MySQLDatabase::GetMasterInfo() {
|
||||||
auto result = ExecuteSelect("SELECT ip, port, master_password FROM servers WHERE name='master' LIMIT 1;");
|
auto result = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||||
|
|
||||||
if (!result->next()) {
|
if (!result->next()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -18,7 +18,6 @@ std::optional<IServers::MasterInfo> MySQLDatabase::GetMasterInfo() {
|
|||||||
|
|
||||||
toReturn.ip = result->getString("ip").c_str();
|
toReturn.ip = result->getString("ip").c_str();
|
||||||
toReturn.port = result->getInt("port");
|
toReturn.port = result->getInt("port");
|
||||||
toReturn.password = result->getString("master_password").c_str();
|
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public:
|
|||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
void UpdatePersistentId(const uint32_t id) override;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "SQLiteDatabase.h"
|
#include "SQLiteDatabase.h"
|
||||||
|
|
||||||
void SQLiteDatabase::SetMasterInfo(const MasterInfo& info) {
|
void SQLiteDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||||
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||||
// since it would be two queries anyways.
|
// since it would be two queries anyways.
|
||||||
ExecuteDelete("DELETE FROM servers;");
|
ExecuteDelete("DELETE FROM servers;");
|
||||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`, `master_password`) VALUES ('master', ?, ?, 0, 171022, ?)", info.ip, info.port, info.password);
|
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
||||||
auto [_, result] = ExecuteSelect("SELECT ip, port, master_password FROM servers WHERE name='master' LIMIT 1;");
|
auto [_, result] = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||||
|
|
||||||
if (result.eof()) {
|
if (result.eof()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -18,7 +18,6 @@ std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
|||||||
|
|
||||||
toReturn.ip = result.getStringField("ip");
|
toReturn.ip = result.getStringField("ip");
|
||||||
toReturn.port = result.getIntField("port");
|
toReturn.port = result.getIntField("port");
|
||||||
toReturn.password = result.getStringField("master_password");
|
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ void TestSQLDatabase::InsertNewAccount(const std::string_view username, const st
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSQLDatabase::SetMasterInfo(const IServers::MasterInfo& info) {
|
void TestSQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class TestSQLDatabase : public GameDatabase {
|
|||||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||||
void InsertDefaultPersistentId() override;
|
void InsertDefaultPersistentId() override;
|
||||||
void UpdatePersistentId(const uint32_t id) override;
|
void UpdatePersistentId(const uint32_t id) override;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
#include "CDPlayerFlagsTable.h"
|
|
||||||
|
|
||||||
Character::Character(uint32_t id, User* parentUser) {
|
Character::Character(uint32_t id, User* parentUser) {
|
||||||
//First load the name, etc:
|
//First load the name, etc:
|
||||||
@@ -232,12 +231,6 @@ void Character::SetBuildMode(bool buildMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Character::SaveXMLToDatabase() {
|
void Character::SaveXMLToDatabase() {
|
||||||
// Check that we can actually _save_ before saving
|
|
||||||
if (!m_OurEntity) {
|
|
||||||
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//For metrics, we'll record the time it took to save:
|
//For metrics, we'll record the time it took to save:
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
@@ -284,19 +277,39 @@ void Character::SaveXMLToDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
||||||
for (const auto& [index, flagBucket] : m_PlayerFlags) {
|
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
|
||||||
auto* f = flags->InsertNewChildElement("f");
|
auto* f = m_Doc.NewElement("f");
|
||||||
f->SetAttribute("id", index);
|
f->SetAttribute("id", flag.first);
|
||||||
f->SetAttribute("v", flagBucket);
|
|
||||||
|
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
|
||||||
|
//Only signed 64-bits ints would work.
|
||||||
|
std::string v = std::to_string(flag.second);
|
||||||
|
f->SetAttribute("v", v.c_str());
|
||||||
|
|
||||||
|
flags->LinkEndChild(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& sessionFlag : m_SessionFlags) {
|
// Prevents the news feed from showing up on world transfers
|
||||||
auto* s = flags->InsertNewChildElement("s");
|
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
|
||||||
s->SetAttribute("si", sessionFlag);
|
auto* s = m_Doc.NewElement("s");
|
||||||
|
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
|
||||||
|
flags->LinkEndChild(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR)) {
|
||||||
|
auto* s = m_Doc.NewElement("s");
|
||||||
|
s->SetAttribute("si", ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR);
|
||||||
|
flags->LinkEndChild(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveXmlRespawnCheckpoints();
|
SaveXmlRespawnCheckpoints();
|
||||||
|
|
||||||
|
//Call upon the entity to update our xmlDoc:
|
||||||
|
if (!m_OurEntity) {
|
||||||
|
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_OurEntity->UpdateXMLDoc(m_Doc);
|
m_OurEntity->UpdateXMLDoc(m_Doc);
|
||||||
|
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
@@ -316,8 +329,8 @@ void Character::SetIsNewLogin() {
|
|||||||
while (currentChild) {
|
while (currentChild) {
|
||||||
auto* nextChild = currentChild->NextSiblingElement();
|
auto* nextChild = currentChild->NextSiblingElement();
|
||||||
if (currentChild->Attribute("si")) {
|
if (currentChild->Attribute("si")) {
|
||||||
LOG("Removed session flag (%s) from character %i:%s, saving character to database", currentChild->Attribute("si"), GetID(), GetName().c_str());
|
|
||||||
flags->DeleteChild(currentChild);
|
flags->DeleteChild(currentChild);
|
||||||
|
LOG("Removed isLoggedIn flag from character %i:%s, saving character to database", GetID(), GetName().c_str());
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
}
|
}
|
||||||
currentChild = nextChild;
|
currentChild = nextChild;
|
||||||
@@ -350,9 +363,7 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId);
|
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
|
||||||
|
|
||||||
if (flagEntry && flagEntry->sessionOnly) {
|
|
||||||
if (value) m_SessionFlags.insert(flagId);
|
if (value) m_SessionFlags.insert(flagId);
|
||||||
else m_SessionFlags.erase(flagId);
|
else m_SessionFlags.erase(flagId);
|
||||||
} else {
|
} else {
|
||||||
@@ -391,8 +402,8 @@ bool Character::GetPlayerFlag(const uint32_t flagId) const {
|
|||||||
|
|
||||||
bool toReturn = false; //by def, return false.
|
bool toReturn = false; //by def, return false.
|
||||||
|
|
||||||
const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId);
|
// TODO make actual session flag checker using flags table in database.
|
||||||
if (flagEntry && flagEntry->sessionOnly) {
|
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
|
||||||
toReturn = m_SessionFlags.contains(flagId);
|
toReturn = m_SessionFlags.contains(flagId);
|
||||||
} else {
|
} else {
|
||||||
// Calculate the index first
|
// Calculate the index first
|
||||||
|
|||||||
@@ -386,9 +386,6 @@ void Entity::Initialize() {
|
|||||||
if (m_Character) {
|
if (m_Character) {
|
||||||
comp->LoadFromXml(m_Character->GetXMLDoc());
|
comp->LoadFromXml(m_Character->GetXMLDoc());
|
||||||
} else {
|
} else {
|
||||||
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
|
|
||||||
comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable);
|
|
||||||
|
|
||||||
if (componentID > 0) {
|
if (componentID > 0) {
|
||||||
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
|
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
|
||||||
|
|
||||||
@@ -423,6 +420,9 @@ void Entity::Initialize() {
|
|||||||
comp->SetMinCoins(currencyValues[0].minvalue);
|
comp->SetMinCoins(currencyValues[0].minvalue);
|
||||||
comp->SetMaxCoins(currencyValues[0].maxvalue);
|
comp->SetMaxCoins(currencyValues[0].maxvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
|
||||||
|
comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
comp->SetHealth(1);
|
comp->SetHealth(1);
|
||||||
@@ -1565,7 +1565,7 @@ void Entity::Kill(Entity* murderer, const eKillType killType) {
|
|||||||
|
|
||||||
m_DieCallbacks.clear();
|
m_DieCallbacks.clear();
|
||||||
|
|
||||||
//お前はもう死んでいる
|
//OMAI WA MOU, SHINDERIU
|
||||||
|
|
||||||
GetScript()->OnDie(this, murderer);
|
GetScript()->OnDie(this, murderer);
|
||||||
|
|
||||||
@@ -2216,17 +2216,3 @@ int32_t Entity::GetCollisionGroup() const {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::HandleMsg(GameMessages::GameMsg& msg) const {
|
|
||||||
bool handled = false;
|
|
||||||
const auto [beg, end] = m_MsgHandlers.equal_range(msg.msgId);
|
|
||||||
for (auto it = beg; it != end; ++it) {
|
|
||||||
if (it->second) handled |= it->second(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
|
||||||
m_MsgHandlers.emplace(msgId, handler);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,17 +14,12 @@
|
|||||||
#include "Observable.h"
|
#include "Observable.h"
|
||||||
|
|
||||||
namespace GameMessages {
|
namespace GameMessages {
|
||||||
struct GameMsg;
|
|
||||||
struct ActivityNotify;
|
struct ActivityNotify;
|
||||||
struct ShootingGalleryFire;
|
struct ShootingGalleryFire;
|
||||||
struct ChildLoaded;
|
struct ChildLoaded;
|
||||||
struct PlayerResurrectionFinished;
|
struct PlayerResurrectionFinished;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace MessageType {
|
|
||||||
enum class Game : uint16_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Loot {
|
namespace Loot {
|
||||||
class Info;
|
class Info;
|
||||||
};
|
};
|
||||||
@@ -321,10 +316,6 @@ public:
|
|||||||
// Scale will only be communicated to the client when the construction packet is sent
|
// Scale will only be communicated to the client when the construction packet is sent
|
||||||
void SetScale(const float scale) { m_Scale = scale; };
|
void SetScale(const float scale) { m_Scale = scale; };
|
||||||
|
|
||||||
void RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler);
|
|
||||||
|
|
||||||
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The observable for player entity position updates.
|
* @brief The observable for player entity position updates.
|
||||||
*/
|
*/
|
||||||
@@ -386,8 +377,6 @@ protected:
|
|||||||
|
|
||||||
// objectID of receiver and map of notification name to script
|
// objectID of receiver and map of notification name to script
|
||||||
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
|
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
|
||||||
|
|
||||||
std::multimap<MessageType::Game, std::function<bool(GameMessages::GameMsg&)>> m_MsgHandlers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include "Mail.h"
|
#include "Mail.h"
|
||||||
#include "ZoneInstanceManager.h"
|
#include "ZoneInstanceManager.h"
|
||||||
#include "WorldPackets.h"
|
#include "WorldPackets.h"
|
||||||
#include "MessageType/Game.h"
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
||||||
@@ -48,45 +47,6 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character, con
|
|||||||
m_CountryCode = 0;
|
m_CountryCode = 0;
|
||||||
m_LastUpdateTimestamp = std::time(nullptr);
|
m_LastUpdateTimestamp = std::time(nullptr);
|
||||||
m_SystemAddress = systemAddress;
|
m_SystemAddress = systemAddress;
|
||||||
|
|
||||||
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &CharacterComponent::OnRequestServerObjectInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|
||||||
auto& request = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
|
||||||
AMFArrayValue response;
|
|
||||||
|
|
||||||
response.Insert("visible", true);
|
|
||||||
response.Insert("objectID", std::to_string(request.targetForReport));
|
|
||||||
response.Insert("serverInfo", true);
|
|
||||||
|
|
||||||
auto& data = *response.InsertArray("data");
|
|
||||||
auto& cmptType = data.PushDebug("Character");
|
|
||||||
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
|
||||||
cmptType.PushDebug<AMFBoolValue>("Last log out time") = m_Character->GetLastLogin();
|
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Seconds played this session") = 0;
|
|
||||||
cmptType.PushDebug<AMFBoolValue>("Editor enabled") = false;
|
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Total number of seconds played") = m_TotalTimePlayed;
|
|
||||||
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
|
||||||
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
|
||||||
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
|
||||||
// visited locations
|
|
||||||
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
|
||||||
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
|
||||||
cmptType.PushDebug<AMFIntValue>("GM Level") = GeneralUtils::ToUnderlying(m_GMLevel);
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Editor level") = GeneralUtils::ToUnderlying(m_EditorLevel);
|
|
||||||
cmptType.PushDebug<AMFStringValue>("Guild ID") = "0";
|
|
||||||
cmptType.PushDebug<AMFStringValue>("Guild Name") = "";
|
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Reputation") = m_Reputation;
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, m_Parent->GetSystemAddress());
|
|
||||||
|
|
||||||
LOG("Handled!");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
||||||
@@ -121,8 +81,6 @@ CharacterComponent::~CharacterComponent() {
|
|||||||
void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||||
|
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
if (!m_Character || !m_Character->GetParentUser()) return;
|
|
||||||
|
|
||||||
outBitStream.Write(m_ClaimCodes[0] != 0);
|
outBitStream.Write(m_ClaimCodes[0] != 0);
|
||||||
if (m_ClaimCodes[0] != 0) outBitStream.Write(m_ClaimCodes[0]);
|
if (m_ClaimCodes[0] != 0) outBitStream.Write(m_ClaimCodes[0]);
|
||||||
outBitStream.Write(m_ClaimCodes[1] != 0);
|
outBitStream.Write(m_ClaimCodes[1] != 0);
|
||||||
@@ -142,7 +100,7 @@ void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInit
|
|||||||
outBitStream.Write(m_Character->GetEyebrows());
|
outBitStream.Write(m_Character->GetEyebrows());
|
||||||
outBitStream.Write(m_Character->GetEyes());
|
outBitStream.Write(m_Character->GetEyes());
|
||||||
outBitStream.Write(m_Character->GetMouth());
|
outBitStream.Write(m_Character->GetMouth());
|
||||||
outBitStream.Write<uint64_t>(m_Character->GetParentUser()->GetAccountID());
|
outBitStream.Write<uint64_t>(0); //AccountID, trying out if 0 works.
|
||||||
outBitStream.Write(m_Character->GetLastLogin()); //Last login
|
outBitStream.Write(m_Character->GetLastLogin()); //Last login
|
||||||
outBitStream.Write<uint64_t>(0); //"prop mod last display time"
|
outBitStream.Write<uint64_t>(0); //"prop mod last display time"
|
||||||
outBitStream.Write<uint64_t>(m_Uscore); //u-score
|
outBitStream.Write<uint64_t>(m_Uscore); //u-score
|
||||||
|
|||||||
@@ -323,8 +323,6 @@ public:
|
|||||||
Character* m_Character;
|
Character* m_Character;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool OnRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of active venture vision effects
|
* The map of active venture vision effects
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ namespace RakNet {
|
|||||||
class BitStream;
|
class BitStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace GameMessages {
|
|
||||||
struct GameMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,10 +52,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
|
||||||
m_Parent->RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity that owns this component
|
* The entity that owns this component
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -84,12 +84,11 @@ dpEntity* PhysicsComponent::CreatePhysicsEntity(eReplicaComponentType type) {
|
|||||||
} else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") {
|
} else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") {
|
||||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true);
|
toReturn = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true);
|
||||||
m_Position.y -= (111.467964f * m_Parent->GetDefaultScale()) / 2;
|
m_Position.y -= (111.467964f * m_Parent->GetDefaultScale()) / 2;
|
||||||
// Leaving these out for now since they cause more issues than they solve in racing tracks without proper OBB checks.
|
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume1_CaveExit.hkx") {
|
||||||
} /* else if (info->physicsAsset == "env\\GFTrack_DeathVolume1_CaveExit.hkx") {
|
|
||||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 112.416870f, 50.363434f, 87.679268f);
|
toReturn = new dpEntity(m_Parent->GetObjectID(), 112.416870f, 50.363434f, 87.679268f);
|
||||||
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume2_RoadGaps.hkx") {
|
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume2_RoadGaps.hkx") {
|
||||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 48.386536f, 50.363434f, 259.361755f);
|
toReturn = new dpEntity(m_Parent->GetObjectID(), 48.386536f, 50.363434f, 259.361755f);
|
||||||
} */ else {
|
} else {
|
||||||
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
||||||
|
|
||||||
//add fallback cube:
|
//add fallback cube:
|
||||||
|
|||||||
@@ -65,7 +65,14 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni
|
|||||||
|
|
||||||
outBitStream.Write(false);
|
outBitStream.Write(false);
|
||||||
}
|
}
|
||||||
|
// If build state is completed and we've already serialized once in the completed state,
|
||||||
|
// don't serializing this component anymore as this will cause the build to jump again.
|
||||||
|
// If state changes, serialization will begin again.
|
||||||
|
if (!m_StateDirty && m_State == eQuickBuildState::COMPLETED) {
|
||||||
|
outBitStream.Write0();
|
||||||
|
outBitStream.Write0();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// BEGIN Scripted Activity
|
// BEGIN Scripted Activity
|
||||||
outBitStream.Write1();
|
outBitStream.Write1();
|
||||||
|
|
||||||
@@ -83,8 +90,8 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni
|
|||||||
}
|
}
|
||||||
// END Scripted Activity
|
// END Scripted Activity
|
||||||
|
|
||||||
outBitStream.Write(m_StateDirty || bIsInitialUpdate);
|
outBitStream.Write1();
|
||||||
if (m_StateDirty || bIsInitialUpdate) {
|
|
||||||
outBitStream.Write(m_State);
|
outBitStream.Write(m_State);
|
||||||
|
|
||||||
outBitStream.Write(m_ShowResetEffect);
|
outBitStream.Write(m_ShowResetEffect);
|
||||||
@@ -94,16 +101,25 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni
|
|||||||
outBitStream.Write(m_TimerIncomplete);
|
outBitStream.Write(m_TimerIncomplete);
|
||||||
|
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
outBitStream.Write(false); // IsChoiceBuild
|
outBitStream.Write(false);
|
||||||
outBitStream.Write(m_ActivatorPosition);
|
outBitStream.Write(m_ActivatorPosition);
|
||||||
outBitStream.Write(m_RepositionPlayer);
|
outBitStream.Write(m_RepositionPlayer);
|
||||||
}
|
}
|
||||||
m_StateDirty = false;
|
m_StateDirty = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void QuickBuildComponent::Update(float deltaTime) {
|
void QuickBuildComponent::Update(float deltaTime) {
|
||||||
SetActivator(GetActivator());
|
m_Activator = GetActivator();
|
||||||
|
|
||||||
|
// Serialize the quickbuild every so often, fixes the odd bug where the quickbuild is not buildable
|
||||||
|
/*if (m_SoftTimer > 0.0f) {
|
||||||
|
m_SoftTimer -= deltaTime;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_SoftTimer = 5.0f;
|
||||||
|
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
}*/
|
||||||
|
|
||||||
switch (m_State) {
|
switch (m_State) {
|
||||||
case eQuickBuildState::OPEN: {
|
case eQuickBuildState::OPEN: {
|
||||||
@@ -114,12 +130,12 @@ void QuickBuildComponent::Update(float deltaTime) {
|
|||||||
const bool isSmashGroup = spawner != nullptr ? spawner->GetIsSpawnSmashGroup() : false;
|
const bool isSmashGroup = spawner != nullptr ? spawner->GetIsSpawnSmashGroup() : false;
|
||||||
|
|
||||||
if (isSmashGroup) {
|
if (isSmashGroup) {
|
||||||
ModifyIncompleteTimer(deltaTime);
|
m_TimerIncomplete += deltaTime;
|
||||||
|
|
||||||
// For reset times < 0 this has to be handled manually
|
// For reset times < 0 this has to be handled manually
|
||||||
if (m_TimeBeforeSmash > 0) {
|
if (m_TimeBeforeSmash > 0) {
|
||||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f && !m_ShowResetEffect) {
|
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
||||||
SetShowResetEffect(true);
|
m_ShowResetEffect = true;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
@@ -137,19 +153,21 @@ void QuickBuildComponent::Update(float deltaTime) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eQuickBuildState::COMPLETED: {
|
case eQuickBuildState::COMPLETED: {
|
||||||
ModifyTimer(deltaTime);
|
m_Timer += deltaTime;
|
||||||
|
|
||||||
// For reset times < 0 this has to be handled manually
|
// For reset times < 0 this has to be handled manually
|
||||||
if (m_ResetTime > 0) {
|
if (m_ResetTime > 0) {
|
||||||
if (m_Timer >= m_ResetTime - 4.0f && !m_ShowResetEffect) {
|
if (m_Timer >= m_ResetTime - 4.0f) {
|
||||||
SetShowResetEffect(true);
|
if (!m_ShowResetEffect) {
|
||||||
|
m_ShowResetEffect = true;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_Timer >= m_ResetTime) {
|
if (m_Timer >= m_ResetTime) {
|
||||||
|
|
||||||
GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 7.0f, false, true);
|
GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
|
||||||
|
|
||||||
ResetQuickBuild(false);
|
ResetQuickBuild(false);
|
||||||
}
|
}
|
||||||
@@ -167,9 +185,9 @@ void QuickBuildComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_TimeBeforeDrain -= deltaTime;
|
m_TimeBeforeDrain -= deltaTime;
|
||||||
ModifyTimer(deltaTime);
|
m_Timer += deltaTime;
|
||||||
SetIncompleteTimer(0.0f);
|
m_TimerIncomplete = 0;
|
||||||
SetShowResetEffect(false);
|
m_ShowResetEffect = false;
|
||||||
|
|
||||||
if (m_TimeBeforeDrain <= 0.0f) {
|
if (m_TimeBeforeDrain <= 0.0f) {
|
||||||
m_TimeBeforeDrain = m_CompleteTime / static_cast<float>(m_TakeImagination);
|
m_TimeBeforeDrain = m_CompleteTime / static_cast<float>(m_TakeImagination);
|
||||||
@@ -197,12 +215,12 @@ void QuickBuildComponent::Update(float deltaTime) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eQuickBuildState::INCOMPLETE: {
|
case eQuickBuildState::INCOMPLETE: {
|
||||||
ModifyIncompleteTimer(deltaTime);
|
m_TimerIncomplete += deltaTime;
|
||||||
|
|
||||||
// For reset times < 0 this has to be handled manually
|
// For reset times < 0 this has to be handled manually
|
||||||
if (m_TimeBeforeSmash > 0) {
|
if (m_TimeBeforeSmash > 0) {
|
||||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f && !m_ShowResetEffect) {
|
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
||||||
SetShowResetEffect(true);
|
m_ShowResetEffect = true;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
@@ -242,7 +260,7 @@ void QuickBuildComponent::SpawnActivator() {
|
|||||||
info.spawnerID = m_Parent->GetObjectID();
|
info.spawnerID = m_Parent->GetObjectID();
|
||||||
info.pos = m_ActivatorPosition == NiPoint3Constant::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition;
|
info.pos = m_ActivatorPosition == NiPoint3Constant::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition;
|
||||||
|
|
||||||
SetActivator(Game::entityManager->CreateEntity(info, nullptr, m_Parent));
|
m_Activator = Game::entityManager->CreateEntity(info, nullptr, m_Parent);
|
||||||
if (m_Activator) {
|
if (m_Activator) {
|
||||||
m_ActivatorId = m_Activator->GetObjectID();
|
m_ActivatorId = m_Activator->GetObjectID();
|
||||||
Game::entityManager->ConstructEntity(m_Activator);
|
Game::entityManager->ConstructEntity(m_Activator);
|
||||||
@@ -259,7 +277,7 @@ void QuickBuildComponent::DespawnActivator() {
|
|||||||
|
|
||||||
m_Activator->ScheduleKillAfterUpdate();
|
m_Activator->ScheduleKillAfterUpdate();
|
||||||
|
|
||||||
SetActivator(nullptr);
|
m_Activator = nullptr;
|
||||||
|
|
||||||
m_ActivatorId = LWOOBJID_EMPTY;
|
m_ActivatorId = LWOOBJID_EMPTY;
|
||||||
}
|
}
|
||||||
@@ -387,7 +405,8 @@ void QuickBuildComponent::StartQuickBuild(Entity* const user) {
|
|||||||
GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::BUILDING, user->GetObjectID());
|
GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::BUILDING, user->GetObjectID());
|
||||||
GameMessages::SendEnableQuickBuild(m_Parent, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID());
|
GameMessages::SendEnableQuickBuild(m_Parent, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID());
|
||||||
|
|
||||||
SetState(eQuickBuildState::BUILDING);
|
m_State = eQuickBuildState::BUILDING;
|
||||||
|
m_StateDirty = true;
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
auto* movingPlatform = m_Parent->GetComponent<MovingPlatformComponent>();
|
auto* movingPlatform = m_Parent->GetComponent<MovingPlatformComponent>();
|
||||||
@@ -425,8 +444,9 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) {
|
|||||||
GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
||||||
|
|
||||||
|
|
||||||
SetState(eQuickBuildState::COMPLETED);
|
m_State = eQuickBuildState::COMPLETED;
|
||||||
SetTimer(0.0f);
|
m_StateDirty = true;
|
||||||
|
m_Timer = 0.0f;
|
||||||
m_DrainedImagination = 0;
|
m_DrainedImagination = 0;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
@@ -506,10 +526,11 @@ void QuickBuildComponent::ResetQuickBuild(const bool failed) {
|
|||||||
|
|
||||||
GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::RESETTING, LWOOBJID_EMPTY);
|
GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::RESETTING, LWOOBJID_EMPTY);
|
||||||
|
|
||||||
SetState(eQuickBuildState::RESETTING);
|
m_State = eQuickBuildState::RESETTING;
|
||||||
SetTimer(0.0f);
|
m_StateDirty = true;
|
||||||
SetIncompleteTimer(0.0f);
|
m_Timer = 0.0f;
|
||||||
SetShowResetEffect(false);
|
m_TimerIncomplete = 0.0f;
|
||||||
|
m_ShowResetEffect = false;
|
||||||
m_DrainedImagination = 0;
|
m_DrainedImagination = 0;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
@@ -542,7 +563,8 @@ void QuickBuildComponent::CancelQuickBuild(Entity* const entity, const eQuickBui
|
|||||||
GameMessages::SendTerminateInteraction(m_Parent->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
GameMessages::SendTerminateInteraction(m_Parent->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
||||||
|
|
||||||
// Now update the component itself
|
// Now update the component itself
|
||||||
SetState(eQuickBuildState::INCOMPLETE);
|
m_State = eQuickBuildState::INCOMPLETE;
|
||||||
|
m_StateDirty = true;
|
||||||
|
|
||||||
// Notify scripts and possible subscribers
|
// Notify scripts and possible subscribers
|
||||||
m_Parent->GetScript()->OnQuickBuildNotifyState(m_Parent, m_State);
|
m_Parent->GetScript()->OnQuickBuildNotifyState(m_Parent, m_State);
|
||||||
|
|||||||
@@ -218,48 +218,6 @@ public:
|
|||||||
* @param skipChecks whether or not to skip the check for the quickbuild not being completed
|
* @param skipChecks whether or not to skip the check for the quickbuild not being completed
|
||||||
*/
|
*/
|
||||||
void CancelQuickBuild(Entity* const builder, const eQuickBuildFailReason failReason, const bool skipChecks = false);
|
void CancelQuickBuild(Entity* const builder, const eQuickBuildFailReason failReason, const bool skipChecks = false);
|
||||||
|
|
||||||
void SetState(const eQuickBuildState state) {
|
|
||||||
if (m_State == state) return;
|
|
||||||
m_State = state;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetShowResetEffect(const bool value) {
|
|
||||||
if (m_ShowResetEffect == value) return;
|
|
||||||
m_ShowResetEffect = value;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetActivator(Entity* const activator) {
|
|
||||||
if (m_Activator == activator) return;
|
|
||||||
m_Activator = activator;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTimer(const float value) {
|
|
||||||
if (m_Timer == value) return;
|
|
||||||
m_Timer = value;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModifyTimer(const float value) {
|
|
||||||
if (value == 0.0f) return;
|
|
||||||
m_Timer += value;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetIncompleteTimer(const float value) {
|
|
||||||
if (m_TimerIncomplete == value) return;
|
|
||||||
m_TimerIncomplete = value;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModifyIncompleteTimer(const float value) {
|
|
||||||
if (value == 0.0f) return;
|
|
||||||
m_TimerIncomplete += value;
|
|
||||||
m_StateDirty = true;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Whether or not the quickbuild state has been changed since we last serialized it.
|
* Whether or not the quickbuild state has been changed since we last serialized it.
|
||||||
|
|||||||
@@ -37,19 +37,8 @@
|
|||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "GhostComponent.h"
|
#include "GhostComponent.h"
|
||||||
#include "eGameMasterLevel.h"
|
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
using enum MessageType::Game;
|
|
||||||
using namespace GameMessages;
|
|
||||||
using MessageCreator = std::function<std::unique_ptr<GameMessages::GameMsg>()>;
|
|
||||||
std::map<MessageType::Game, MessageCreator> g_MessageHandlers = {
|
|
||||||
{ REQUEST_SERVER_OBJECT_INFO, []() { return std::make_unique<RequestServerObjectInfo>(); } },
|
|
||||||
{ SHOOTING_GALLERY_FIRE, []() { return std::make_unique<ShootingGalleryFire>(); } },
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) {
|
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) {
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
@@ -66,24 +55,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
|||||||
|
|
||||||
if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
||||||
|
|
||||||
auto handler = g_MessageHandlers.find(messageID);
|
|
||||||
if (handler != g_MessageHandlers.end()) {
|
|
||||||
auto msg = handler->second();
|
|
||||||
|
|
||||||
// Verify that the system address user is able to use this message.
|
|
||||||
if (msg->requiredGmLevel > eGameMasterLevel::CIVILIAN) {
|
|
||||||
auto* usingEntity = Game::entityManager->GetEntity(usr->GetLoggedInChar());
|
|
||||||
if (!usingEntity || usingEntity->GetGMLevel() < msg->requiredGmLevel) {
|
|
||||||
LOG("User %s (%llu) does not have the required GM level to execute this command.", usingEntity->GetCharacter()->GetName().c_str(), usingEntity->GetObjectID());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg->Deserialize(inStream);
|
|
||||||
msg->Handle(*entity, sysAddr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (messageID) {
|
switch (messageID) {
|
||||||
|
|
||||||
case MessageType::Game::UN_USE_BBB_MODEL: {
|
case MessageType::Game::UN_USE_BBB_MODEL: {
|
||||||
@@ -733,6 +704,12 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
|||||||
case MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS:
|
case MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS:
|
||||||
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
|
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
|
||||||
break;
|
break;
|
||||||
|
case MessageType::Game::SHOOTING_GALLERY_FIRE: {
|
||||||
|
GameMessages::ShootingGalleryFire fire{};
|
||||||
|
fire.Deserialize(inStream);
|
||||||
|
fire.Handle(*entity, sysAddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
||||||
|
|||||||
@@ -843,10 +843,8 @@ void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, c
|
|||||||
|
|
||||||
bitStream.Write(entity->GetObjectID());
|
bitStream.Write(entity->GetObjectID());
|
||||||
bitStream.Write(MessageType::Game::DIE);
|
bitStream.Write(MessageType::Game::DIE);
|
||||||
|
|
||||||
bitStream.Write(bClientDeath);
|
bitStream.Write(bClientDeath);
|
||||||
bitStream.Write(bSpawnLoot);
|
bitStream.Write(bSpawnLoot);
|
||||||
bitStream.Write<uint32_t>(deathType.size());
|
|
||||||
bitStream.Write(deathType);
|
bitStream.Write(deathType);
|
||||||
bitStream.Write(directionRelative_AngleXZ);
|
bitStream.Write(directionRelative_AngleXZ);
|
||||||
bitStream.Write(directionRelative_AngleY);
|
bitStream.Write(directionRelative_AngleY);
|
||||||
@@ -856,10 +854,7 @@ void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, c
|
|||||||
if (killType != eKillType::VIOLENT) bitStream.Write(killType);
|
if (killType != eKillType::VIOLENT) bitStream.Write(killType);
|
||||||
|
|
||||||
bitStream.Write(killerID);
|
bitStream.Write(killerID);
|
||||||
bitStream.Write(lootOwnerID != LWOOBJID_EMPTY);
|
|
||||||
if (lootOwnerID != LWOOBJID_EMPTY) {
|
|
||||||
bitStream.Write(lootOwnerID);
|
bitStream.Write(lootOwnerID);
|
||||||
}
|
|
||||||
|
|
||||||
SEND_PACKET_BROADCAST;
|
SEND_PACKET_BROADCAST;
|
||||||
}
|
}
|
||||||
@@ -6431,16 +6426,4 @@ namespace GameMessages {
|
|||||||
void ShootingGalleryFire::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
void ShootingGalleryFire::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||||
entity.OnShootingGalleryFire(*this);
|
entity.OnShootingGalleryFire(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RequestServerObjectInfo::Deserialize(RakNet::BitStream& bitStream) {
|
|
||||||
if (!bitStream.Read(bVerbose)) return false;
|
|
||||||
if (!bitStream.Read(clientId)) return false;
|
|
||||||
if (!bitStream.Read(targetForReport)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RequestServerObjectInfo::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
|
||||||
auto* handlingEntity = Game::entityManager->GetEntity(targetForReport);
|
|
||||||
if (handlingEntity) handlingEntity->HandleMsg(*this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include "eLootSourceType.h"
|
#include "eLootSourceType.h"
|
||||||
#include "Brick.h"
|
#include "Brick.h"
|
||||||
#include "MessageType/Game.h"
|
#include "MessageType/Game.h"
|
||||||
#include "eGameMasterLevel.h"
|
|
||||||
|
|
||||||
class AMFBaseValue;
|
class AMFBaseValue;
|
||||||
class Entity;
|
class Entity;
|
||||||
@@ -51,8 +50,7 @@ enum class eCameraTargetCyclingMode : int32_t {
|
|||||||
|
|
||||||
namespace GameMessages {
|
namespace GameMessages {
|
||||||
struct GameMsg {
|
struct GameMsg {
|
||||||
GameMsg(MessageType::Game gmId, eGameMasterLevel lvl) : msgId{ gmId }, requiredGmLevel{ lvl } {}
|
GameMsg(MessageType::Game gmId) : msgId{ gmId } {}
|
||||||
GameMsg(MessageType::Game gmId) : GameMsg(gmId, eGameMasterLevel::CIVILIAN) {}
|
|
||||||
virtual ~GameMsg() = default;
|
virtual ~GameMsg() = default;
|
||||||
void Send(const SystemAddress& sysAddr) const;
|
void Send(const SystemAddress& sysAddr) const;
|
||||||
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
||||||
@@ -60,7 +58,6 @@ namespace GameMessages {
|
|||||||
virtual void Handle(Entity& entity, const SystemAddress& sysAddr) {};
|
virtual void Handle(Entity& entity, const SystemAddress& sysAddr) {};
|
||||||
MessageType::Game msgId;
|
MessageType::Game msgId;
|
||||||
LWOOBJID target{ LWOOBJID_EMPTY };
|
LWOOBJID target{ LWOOBJID_EMPTY };
|
||||||
eGameMasterLevel requiredGmLevel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PropertyDataMessage;
|
class PropertyDataMessage;
|
||||||
@@ -772,16 +769,6 @@ namespace GameMessages {
|
|||||||
struct PlayerResurrectionFinished : public GameMsg {
|
struct PlayerResurrectionFinished : public GameMsg {
|
||||||
PlayerResurrectionFinished() : GameMsg(MessageType::Game::PLAYER_RESURRECTION_FINISHED) {}
|
PlayerResurrectionFinished() : GameMsg(MessageType::Game::PLAYER_RESURRECTION_FINISHED) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RequestServerObjectInfo : public GameMsg {
|
|
||||||
bool bVerbose{};
|
|
||||||
LWOOBJID clientId{};
|
|
||||||
LWOOBJID targetForReport{};
|
|
||||||
|
|
||||||
RequestServerObjectInfo() : GameMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, eGameMasterLevel::DEVELOPER) {}
|
|
||||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
|
||||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GAMEMESSAGES_H
|
#endif // GAMEMESSAGES_H
|
||||||
|
|||||||
@@ -62,14 +62,6 @@ std::map<uint32_t, std::string> activeSessions;
|
|||||||
SystemAddress authServerMasterPeerSysAddr;
|
SystemAddress authServerMasterPeerSysAddr;
|
||||||
SystemAddress chatServerMasterPeerSysAddr;
|
SystemAddress chatServerMasterPeerSysAddr;
|
||||||
|
|
||||||
int GenerateBCryptPassword(const std::string& password, const int workFactor, char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) {
|
|
||||||
int32_t bcryptState = ::bcrypt_gensalt(workFactor, salt);
|
|
||||||
assert(bcryptState == 0);
|
|
||||||
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
|
||||||
assert(bcryptState == 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
constexpr uint32_t masterFramerate = mediumFramerate;
|
constexpr uint32_t masterFramerate = mediumFramerate;
|
||||||
constexpr uint32_t masterFrameDelta = mediumFrameDelta;
|
constexpr uint32_t masterFrameDelta = mediumFrameDelta;
|
||||||
@@ -246,7 +238,10 @@ int main(int argc, char** argv) {
|
|||||||
// Regenerate hash based on new password
|
// Regenerate hash based on new password
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
int32_t bcryptState = ::bcrypt_gensalt(12, salt);
|
||||||
|
assert(bcryptState == 0);
|
||||||
|
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
||||||
|
assert(bcryptState == 0);
|
||||||
|
|
||||||
Database::Get()->UpdateAccountPassword(accountId->id, std::string(hash, BCRYPT_HASHSIZE));
|
Database::Get()->UpdateAccountPassword(accountId->id, std::string(hash, BCRYPT_HASHSIZE));
|
||||||
|
|
||||||
@@ -284,7 +279,10 @@ int main(int argc, char** argv) {
|
|||||||
//Generate new hash for bcrypt
|
//Generate new hash for bcrypt
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
int32_t bcryptState = ::bcrypt_gensalt(12, salt);
|
||||||
|
assert(bcryptState == 0);
|
||||||
|
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
||||||
|
assert(bcryptState == 0);
|
||||||
|
|
||||||
//Create account
|
//Create account
|
||||||
try {
|
try {
|
||||||
@@ -320,24 +318,15 @@ int main(int argc, char** argv) {
|
|||||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||||
|
|
||||||
char salt[BCRYPT_HASHSIZE];
|
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal);
|
||||||
char hash[BCRYPT_HASHSIZE];
|
|
||||||
const auto& cfgPassword = Game::config->GetValue("master_password");
|
|
||||||
GenerateBCryptPassword(!cfgPassword.empty() ? cfgPassword : "3.25DARKFLAME1", 13, salt, hash);
|
|
||||||
|
|
||||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal, hash);
|
|
||||||
|
|
||||||
std::string master_server_ip = "localhost";
|
std::string master_server_ip = "localhost";
|
||||||
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
||||||
if (!masterServerIPString.empty()) master_server_ip = masterServerIPString;
|
if (!masterServerIPString.empty()) master_server_ip = masterServerIPString;
|
||||||
|
|
||||||
if (master_server_ip == "") master_server_ip = Game::server->GetIP();
|
if (master_server_ip == "") master_server_ip = Game::server->GetIP();
|
||||||
IServers::MasterInfo info;
|
|
||||||
info.ip = master_server_ip;
|
|
||||||
info.port = Game::server->GetPort();
|
|
||||||
info.password = hash;
|
|
||||||
|
|
||||||
Database::Get()->SetMasterInfo(info);
|
Database::Get()->SetMasterIp(master_server_ip, Game::server->GetPort());
|
||||||
|
|
||||||
//Create additional objects here:
|
//Create additional objects here:
|
||||||
PersistentIDManager::Initialize();
|
PersistentIDManager::Initialize();
|
||||||
|
|||||||
@@ -3,3 +3,4 @@
|
|||||||
#include "RakPeer.h"
|
#include "RakPeer.h"
|
||||||
|
|
||||||
#define NET_PASSWORD_EXTERNAL "3.25 ND1"
|
#define NET_PASSWORD_EXTERNAL "3.25 ND1"
|
||||||
|
#define NET_PASSWORD_INTERNAL "3.25 DARKFLAME1"
|
||||||
|
|||||||
@@ -40,21 +40,7 @@ public:
|
|||||||
}
|
}
|
||||||
} ReceiveDownloadCompleteCB;
|
} ReceiveDownloadCompleteCB;
|
||||||
|
|
||||||
dServer::dServer(
|
dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
|
||||||
const std::string& ip,
|
|
||||||
int port,
|
|
||||||
int instanceID,
|
|
||||||
int maxConnections,
|
|
||||||
bool isInternal,
|
|
||||||
bool useEncryption,
|
|
||||||
Logger* logger,
|
|
||||||
const std::string masterIP,
|
|
||||||
int masterPort,
|
|
||||||
ServerType serverType,
|
|
||||||
dConfig* config,
|
|
||||||
Game::signal_t* lastSignal,
|
|
||||||
const std::string& masterPassword,
|
|
||||||
unsigned int zoneID) {
|
|
||||||
mIP = ip;
|
mIP = ip;
|
||||||
mPort = port;
|
mPort = port;
|
||||||
mZoneID = zoneID;
|
mZoneID = zoneID;
|
||||||
@@ -70,7 +56,6 @@ dServer::dServer(
|
|||||||
mReplicaManager = nullptr;
|
mReplicaManager = nullptr;
|
||||||
mServerType = serverType;
|
mServerType = serverType;
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mMasterPassword = masterPassword;
|
|
||||||
mShouldShutdown = lastSignal;
|
mShouldShutdown = lastSignal;
|
||||||
//Attempt to start our server here:
|
//Attempt to start our server here:
|
||||||
mIsOkay = Startup();
|
mIsOkay = Startup();
|
||||||
@@ -218,11 +203,11 @@ bool dServer::Startup() {
|
|||||||
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
||||||
|
|
||||||
if (mIsInternal) {
|
if (mIsInternal) {
|
||||||
mPeer->SetIncomingPassword(mMasterPassword.c_str(), mMasterPassword.size());
|
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
||||||
} else {
|
} else {
|
||||||
UpdateBandwidthLimit();
|
UpdateBandwidthLimit();
|
||||||
UpdateMaximumMtuSize();
|
UpdateMaximumMtuSize();
|
||||||
mPeer->SetIncomingPassword(NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
||||||
@@ -272,7 +257,7 @@ void dServer::SetupForMasterConnection() {
|
|||||||
|
|
||||||
bool dServer::ConnectToMaster() {
|
bool dServer::ConnectToMaster() {
|
||||||
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
||||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, mMasterPassword.c_str(), mMasterPassword.size());
|
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dServer::UpdateReplica() {
|
void dServer::UpdateReplica() {
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ public:
|
|||||||
ServerType serverType,
|
ServerType serverType,
|
||||||
dConfig* config,
|
dConfig* config,
|
||||||
Game::signal_t* shouldShutdown,
|
Game::signal_t* shouldShutdown,
|
||||||
const std::string& masterPassword,
|
|
||||||
unsigned int zoneID = 0);
|
unsigned int zoneID = 0);
|
||||||
~dServer();
|
~dServer();
|
||||||
|
|
||||||
@@ -122,5 +121,4 @@ protected:
|
|||||||
std::string mMasterIP;
|
std::string mMasterIP;
|
||||||
int mMasterPort;
|
int mMasterPort;
|
||||||
std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now();
|
||||||
std::string mMasterPassword;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,38 +10,49 @@ void NsLegoClubDoor::OnStartup(Entity* self) {
|
|||||||
self->SetVar(u"teleportString", m_TeleportString);
|
self->SetVar(u"teleportString", m_TeleportString);
|
||||||
self->SetVar(u"spawnPoint", m_SpawnPoint);
|
self->SetVar(u"spawnPoint", m_SpawnPoint);
|
||||||
|
|
||||||
teleportArgs.Reset();
|
args = {};
|
||||||
|
|
||||||
teleportArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
args.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
||||||
teleportArgs.Insert("strIdentifier", "choiceDoor");
|
args.Insert("strIdentifier", "choiceDoor");
|
||||||
teleportArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
args.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
||||||
|
|
||||||
auto& choiceOptions = *teleportArgs.InsertArray("options");
|
AMFArrayValue* choiceOptions = args.InsertArray("options");
|
||||||
|
|
||||||
{
|
{
|
||||||
auto& nsArgs = *choiceOptions.PushArray();
|
AMFArrayValue* nsArgs = choiceOptions->PushArray();
|
||||||
|
|
||||||
nsArgs.Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
|
nsArgs->Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
|
||||||
nsArgs.Insert("caption", "%[UI_CHOICE_NS]");
|
nsArgs->Insert("caption", "%[UI_CHOICE_NS]");
|
||||||
nsArgs.Insert("identifier", "zoneID_1200");
|
nsArgs->Insert("identifier", "zoneID_1200");
|
||||||
nsArgs.Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
|
nsArgs->Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto& ntArgs = *choiceOptions.PushArray();
|
AMFArrayValue* ntArgs = choiceOptions->PushArray();
|
||||||
|
|
||||||
ntArgs.Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
|
ntArgs->Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
|
||||||
ntArgs.Insert("caption", "%[UI_CHOICE_NT]");
|
ntArgs->Insert("caption", "%[UI_CHOICE_NT]");
|
||||||
ntArgs.Insert("identifier", "zoneID_1900");
|
ntArgs->Insert("identifier", "zoneID_1900");
|
||||||
ntArgs.Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
|
ntArgs->Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options = choiceOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NsLegoClubDoor::OnUse(Entity* self, Entity* user) {
|
void NsLegoClubDoor::OnUse(Entity* self, Entity* user) {
|
||||||
auto* player = user;
|
auto* player = user;
|
||||||
|
|
||||||
if (CheckChoice(self, player)) {
|
if (CheckChoice(self, player)) {
|
||||||
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", teleportArgs);
|
AMFArrayValue multiArgs;
|
||||||
|
|
||||||
|
multiArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
||||||
|
multiArgs.Insert("strIdentifier", "choiceDoor");
|
||||||
|
multiArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
||||||
|
multiArgs.Insert("options", static_cast<AMFBaseValue*>(options));
|
||||||
|
|
||||||
|
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", multiArgs);
|
||||||
|
|
||||||
|
multiArgs.Remove("options", false); // We do not want the local amf to delete the options!
|
||||||
} else if (self->GetVar<int32_t>(u"currentZone") != m_ChoiceZoneID) {
|
} else if (self->GetVar<int32_t>(u"currentZone") != m_ChoiceZoneID) {
|
||||||
AMFArrayValue multiArgs;
|
AMFArrayValue multiArgs;
|
||||||
multiArgs.Insert("state", "Lobby");
|
multiArgs.Insert("state", "Lobby");
|
||||||
|
|||||||
@@ -19,5 +19,6 @@ private:
|
|||||||
std::string m_SpawnPoint = "NS_LEGO_Club";
|
std::string m_SpawnPoint = "NS_LEGO_Club";
|
||||||
std::u16string m_TeleportAnim = u"lup-teleport";
|
std::u16string m_TeleportAnim = u"lup-teleport";
|
||||||
std::u16string m_TeleportString = u"ROCKET_TOOLTIP_USE_THE_GATEWAY_TO_TRAVEL_TO_LUP_WORLD";
|
std::u16string m_TeleportString = u"ROCKET_TOOLTIP_USE_THE_GATEWAY_TO_TRAVEL_TO_LUP_WORLD";
|
||||||
AMFArrayValue teleportArgs{};
|
AMFArrayValue args = {};
|
||||||
|
AMFArrayValue* options = {};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) {
|
|||||||
|
|
||||||
auto box = GetBox(self);
|
auto box = GetBox(self);
|
||||||
// knockback the target
|
// knockback the target
|
||||||
auto forward = self->GetRotation().GetForwardVector();
|
auto forward = target->GetRotation().GetForwardVector();
|
||||||
box.boxTarget = target->GetObjectID();
|
box.boxTarget = target->GetObjectID();
|
||||||
GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack");
|
GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack");
|
||||||
RenderComponent::PlayAnimation(target, "knockback-recovery");
|
RenderComponent::PlayAnimation(target, "knockback-recovery");
|
||||||
forward.y += 15;
|
forward.y += 15;
|
||||||
forward.x *= 100;
|
forward.x *= 100;
|
||||||
forward.z *= 100;
|
forward.z *= 100;
|
||||||
GameMessages::SendKnockback(target->GetObjectID(), LWOOBJID_EMPTY, LWOOBJID_EMPTY, 0, forward);
|
GameMessages::SendKnockback(target->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, forward);
|
||||||
|
|
||||||
if (box.isTouch || box.isDisplayed) return;
|
if (box.isTouch || box.isDisplayed) return;
|
||||||
box.boxSelf = self->GetObjectID();
|
box.boxSelf = self->GetObjectID();
|
||||||
|
|||||||
@@ -202,13 +202,11 @@ int main(int argc, char** argv) {
|
|||||||
//Find out the master's IP:
|
//Find out the master's IP:
|
||||||
std::string masterIP = "localhost";
|
std::string masterIP = "localhost";
|
||||||
uint32_t masterPort = 1000;
|
uint32_t masterPort = 1000;
|
||||||
std::string masterPassword;
|
|
||||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||||
|
|
||||||
if (masterInfo) {
|
if (masterInfo) {
|
||||||
masterIP = masterInfo->ip;
|
masterIP = masterInfo->ip;
|
||||||
masterPort = masterInfo->port;
|
masterPort = masterInfo->port;
|
||||||
masterPassword = masterInfo->password;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UserManager::Instance()->Initialize();
|
UserManager::Instance()->Initialize();
|
||||||
@@ -216,7 +214,7 @@ int main(int argc, char** argv) {
|
|||||||
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
||||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||||
|
|
||||||
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, masterPassword, zoneID);
|
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, zoneID);
|
||||||
|
|
||||||
//Connect to the chat server:
|
//Connect to the chat server:
|
||||||
uint32_t chatPort = 1501;
|
uint32_t chatPort = 1501;
|
||||||
@@ -225,7 +223,7 @@ int main(int argc, char** argv) {
|
|||||||
auto chatSock = SocketDescriptor(static_cast<uint16_t>(ourPort + 2), 0);
|
auto chatSock = SocketDescriptor(static_cast<uint16_t>(ourPort + 2), 0);
|
||||||
Game::chatServer = RakNetworkFactory::GetRakPeerInterface();
|
Game::chatServer = RakNetworkFactory::GetRakPeerInterface();
|
||||||
Game::chatServer->Startup(1, 30, &chatSock, 1);
|
Game::chatServer->Startup(1, 30, &chatSock, 1);
|
||||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||||
|
|
||||||
//Set up other things:
|
//Set up other things:
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
@@ -373,7 +371,7 @@ int main(int argc, char** argv) {
|
|||||||
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
||||||
framesSinceChatDisconnect = 0;
|
framesSinceChatDisconnect = 0;
|
||||||
|
|
||||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||||
}
|
}
|
||||||
} else framesSinceChatDisconnect = 0;
|
} else framesSinceChatDisconnect = 0;
|
||||||
|
|
||||||
|
|||||||
BIN
docs/setup.png
BIN
docs/setup.png
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE servers ADD COLUMN master_password TEXT NOT NULL DEFAULT ('3.25 DARKFLAME1');
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE servers ADD COLUMN master_password TEXT NOT NULL DEFAULT ('3.25 DARKFLAME1');
|
|
||||||
@@ -9,5 +9,3 @@ world_port_start=3000
|
|||||||
|
|
||||||
# 0 or 1, should autostart auth, chat, and char servers
|
# 0 or 1, should autostart auth, chat, and char servers
|
||||||
prestart_servers=1
|
prestart_servers=1
|
||||||
|
|
||||||
master_password=3.25DARKFLAME1
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ dump_folder=
|
|||||||
|
|
||||||
# The location of the client
|
# The location of the client
|
||||||
# Either the folder with /res or with /client and /versions
|
# Either the folder with /res or with /client and /versions
|
||||||
client_location=..
|
client_location=
|
||||||
|
|
||||||
# The maximum outgoing bandwidth in bits. If your clients are having
|
# The maximum outgoing bandwidth in bits. If your clients are having
|
||||||
# issues with enemies taking a while to catch up to them, increse this value.
|
# issues with enemies taking a while to catch up to them, increse this value.
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ TEST(dCommonTests, AMF3InsertionAssociativeTest) {
|
|||||||
array.Insert<int32_t>("Integer", 42U);
|
array.Insert<int32_t>("Integer", 42U);
|
||||||
array.Insert("Double", 42.0);
|
array.Insert("Double", 42.0);
|
||||||
array.InsertArray("Array");
|
array.InsertArray("Array");
|
||||||
array.Insert<std::vector<uint32_t>>("Undefined", std::vector<uint32_t>{});
|
array.Insert<std::vector<uint32_t>>("Undefined", {});
|
||||||
array.Insert("Null", nullptr);
|
array.Insert("Null", nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
|
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
|
||||||
|
|||||||
6
thirdparty/SQLite/CppSQLite3.cpp
vendored
6
thirdparty/SQLite/CppSQLite3.cpp
vendored
@@ -573,18 +573,16 @@ bool CppSQLite3Query::eof()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CppSQLite3Query::nextRow()
|
void CppSQLite3Query::nextRow()
|
||||||
{
|
{
|
||||||
checkVM();
|
checkVM();
|
||||||
|
|
||||||
int nRet = sqlite3_step(mpVM);
|
int nRet = sqlite3_step(mpVM);
|
||||||
|
|
||||||
bool bRet = true;
|
|
||||||
if (nRet == SQLITE_DONE)
|
if (nRet == SQLITE_DONE)
|
||||||
{
|
{
|
||||||
// no rows
|
// no rows
|
||||||
mbEof = true;
|
mbEof = true;
|
||||||
bRet = false;
|
|
||||||
}
|
}
|
||||||
else if (nRet == SQLITE_ROW)
|
else if (nRet == SQLITE_ROW)
|
||||||
{
|
{
|
||||||
@@ -592,7 +590,6 @@ bool CppSQLite3Query::nextRow()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bRet = false;
|
|
||||||
nRet = sqlite3_finalize(mpVM);
|
nRet = sqlite3_finalize(mpVM);
|
||||||
mpVM = 0;
|
mpVM = 0;
|
||||||
const char* szError = sqlite3_errmsg(mpDB);
|
const char* szError = sqlite3_errmsg(mpDB);
|
||||||
@@ -600,7 +597,6 @@ bool CppSQLite3Query::nextRow()
|
|||||||
(char*)szError,
|
(char*)szError,
|
||||||
DONT_DELETE_MSG);
|
DONT_DELETE_MSG);
|
||||||
}
|
}
|
||||||
return bRet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
thirdparty/SQLite/CppSQLite3.h
vendored
10
thirdparty/SQLite/CppSQLite3.h
vendored
@@ -165,8 +165,7 @@ public:
|
|||||||
|
|
||||||
bool eof();
|
bool eof();
|
||||||
|
|
||||||
// Returns true if there is another row to read, false otherwise.
|
void nextRow();
|
||||||
bool nextRow();
|
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
@@ -208,9 +207,6 @@ public:
|
|||||||
int getIntField(int nField, int nNullValue=0);
|
int getIntField(int nField, int nNullValue=0);
|
||||||
int getIntField(const char* szField, int nNullValue=0);
|
int getIntField(const char* szField, int nNullValue=0);
|
||||||
|
|
||||||
sqlite_int64 getInt64Field(int nField, sqlite_int64 nNullValue=0);
|
|
||||||
sqlite_int64 getInt64Field(const char* szField, sqlite_int64 nNullValue=0);
|
|
||||||
|
|
||||||
double getFloatField(int nField, double fNullValue=0.0);
|
double getFloatField(int nField, double fNullValue=0.0);
|
||||||
double getFloatField(const char* szField, double fNullValue=0.0);
|
double getFloatField(const char* szField, double fNullValue=0.0);
|
||||||
|
|
||||||
@@ -222,9 +218,6 @@ public:
|
|||||||
|
|
||||||
void setRow(int nRow);
|
void setRow(int nRow);
|
||||||
|
|
||||||
// Returns true if there is another row to read, false otherwise.
|
|
||||||
bool nextRow();
|
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -233,7 +226,6 @@ private:
|
|||||||
|
|
||||||
int mnCols;
|
int mnCols;
|
||||||
int mnRows;
|
int mnRows;
|
||||||
bool mbEof;
|
|
||||||
int mnCurrentRow;
|
int mnCurrentRow;
|
||||||
char** mpaszResults;
|
char** mpaszResults;
|
||||||
};
|
};
|
||||||
|
|||||||
2
thirdparty/raknet/CMakeLists.txt
vendored
2
thirdparty/raknet/CMakeLists.txt
vendored
@@ -59,7 +59,7 @@ Source/DS_List.h Source/NetworkIDObject.h S
|
|||||||
Source/DS_Map.h Source/PacketConsoleLogger.h Source/SingleProducerConsumer.h
|
Source/DS_Map.h Source/PacketConsoleLogger.h Source/SingleProducerConsumer.h
|
||||||
Source/DS_MemoryPool.h Source/PacketFileLogger.h Source/SocketLayer.h
|
Source/DS_MemoryPool.h Source/PacketFileLogger.h Source/SocketLayer.h
|
||||||
Source/DS_OrderedChannelHeap.h Source/PacketLogger.h Source/StringCompressor.h
|
Source/DS_OrderedChannelHeap.h Source/PacketLogger.h Source/StringCompressor.h
|
||||||
Source/DS_OrderedList.h Source/StringTable.h
|
Source/DS_OrderedList.h Source/PacketPool.h Source/StringTable.h
|
||||||
Source/DS_Queue.h Source/PacketPriority.h Source/SystemAddressList.h
|
Source/DS_Queue.h Source/PacketPriority.h Source/SystemAddressList.h
|
||||||
Source/DS_QueueLinkedList.h Source/PluginInterface.h Source/TableSerializer.h
|
Source/DS_QueueLinkedList.h Source/PluginInterface.h Source/TableSerializer.h
|
||||||
Source/DS_RangeList.h Source/RakAssert.h Source/TCPInterface.h
|
Source/DS_RangeList.h Source/RakAssert.h Source/TCPInterface.h
|
||||||
|
|||||||
1
thirdparty/raknet/Source/PacketPool.h
vendored
Normal file
1
thirdparty/raknet/Source/PacketPool.h
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// REMOVEME
|
||||||
Reference in New Issue
Block a user