This commit is contained in:
Aaron Kimbrell
2026-02-24 20:35:09 -06:00
parent f1847d1f20
commit 910b92ffc7
24 changed files with 883 additions and 180 deletions

View File

@@ -1,17 +1,12 @@
set(DDASHBOARDSERVER_SOURCES set(DDASHBOARDSERVER_SOURCES
"DashboardServer.cpp" "DashboardServer.cpp"
"MasterPacketHandler.cpp" "handlers/MasterPacketHandler.cpp"
"routes/APIRoutes.cpp" "handlers/DashboardPacketHandler.cpp"
"routes/StaticRoutes.cpp"
"routes/DashboardRoutes.cpp"
"routes/WSRoutes.cpp"
"routes/AuthRoutes.cpp"
"auth/JWTUtils.cpp"
"auth/DashboardAuthService.cpp"
"auth/AuthMiddleware.cpp"
"auth/RequireAuthMiddleware.cpp"
) )
add_subdirectory(routes)
add_subdirectory(auth)
add_executable(DashboardServer ${DDASHBOARDSERVER_SOURCES}) add_executable(DashboardServer ${DDASHBOARDSERVER_SOURCES})
target_include_directories(DashboardServer PRIVATE target_include_directories(DashboardServer PRIVATE
@@ -29,11 +24,12 @@ target_include_directories(DashboardServer PRIVATE
"${PROJECT_SOURCE_DIR}/dServer" "${PROJECT_SOURCE_DIR}/dServer"
"${PROJECT_SOURCE_DIR}/thirdparty" "${PROJECT_SOURCE_DIR}/thirdparty"
"${PROJECT_SOURCE_DIR}/thirdparty/nlohmann" "${PROJECT_SOURCE_DIR}/thirdparty/nlohmann"
"${PROJECT_SOURCE_DIR}/dDashboardServer"
"${PROJECT_SOURCE_DIR}/dDashboardServer/auth" "${PROJECT_SOURCE_DIR}/dDashboardServer/auth"
"${PROJECT_SOURCE_DIR}/dDashboardServer/routes" "${PROJECT_SOURCE_DIR}/dDashboardServer/routes"
) )
target_link_libraries(DashboardServer ${COMMON_LIBRARIES} dWeb dServer bcrypt OpenSSL::Crypto) target_link_libraries(DashboardServer ${COMMON_LIBRARIES} dWeb dServer bcrypt OpenSSL::Crypto DashboardRoutes DashboardAuth)
# Copy static files and templates to build directory (always copy) # Copy static files and templates to build directory (always copy)

View File

@@ -20,14 +20,16 @@
#include "Diagnostics.h" #include "Diagnostics.h"
#include "Web.h" #include "Web.h"
#include "Server.h" #include "Server.h"
#include "MasterPacketHandler.h" #include "PacketHandler.h"
#include "handlers/MasterPacketHandler.h"
#include "handlers/DashboardPacketHandler.h"
#include "routes/ServerState.h" #include "ServerState.h"
#include "routes/APIRoutes.h" #include "APIRoutes.h"
#include "routes/StaticRoutes.h" #include "StaticRoutes.h"
#include "routes/DashboardRoutes.h" #include "DashboardRoutes.h"
#include "routes/WSRoutes.h" #include "WSRoutes.h"
#include "routes/AuthRoutes.h" #include "AuthRoutes.h"
#include "AuthMiddleware.h" #include "AuthMiddleware.h"
namespace Game { namespace Game {
@@ -97,6 +99,9 @@ int main(int argc, char** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Register dashboard-specific packet handlers
DashboardPacketHandler::RegisterDashboardHandlers();
// Get master info from database // Get master info from database
std::string masterIP = "localhost"; std::string masterIP = "localhost";
uint32_t masterPort = 1000; uint32_t masterPort = 1000;
@@ -160,10 +165,20 @@ int main(int argc, char** argv) {
// Handle master server packets // Handle master server packets
Packet* packet = g_Server->ReceiveFromMaster(); Packet* packet = g_Server->ReceiveFromMaster();
if (packet) { if (packet) {
MasterPacketHandler::HandleMasterPacket(packet); RakNet::BitStream bitStream(packet->data, packet->length, false);
PacketHandler::HandlePacket(bitStream, packet->systemAddress);
g_Server->DeallocateMasterPacket(packet); g_Server->DeallocateMasterPacket(packet);
} }
// Handle RakNet protocol packets from connected servers
packet = g_Server->Receive();
while (packet) {
RakNet::BitStream bitStream(packet->data, packet->length, false);
PacketHandler::HandlePacket(bitStream, packet->systemAddress);
g_Server->DeallocatePacket(packet);
packet = g_Server->Receive();
}
// Handle web requests // Handle web requests
Game::web.ReceiveRequests(); Game::web.ReceiveRequests();

View File

@@ -0,0 +1,28 @@
set(DASHBOARDAUTH_SOURCES
"JWTUtils.cpp"
"DashboardAuthService.cpp"
"AuthMiddleware.cpp"
"RequireAuthMiddleware.cpp"
)
add_library(DashboardAuth STATIC ${DASHBOARDAUTH_SOURCES})
target_include_directories(DashboardAuth PRIVATE
"${PROJECT_SOURCE_DIR}/dCommon"
"${PROJECT_SOURCE_DIR}/dCommon/dClient"
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
"${PROJECT_SOURCE_DIR}/dDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/MySQL"
"${PROJECT_SOURCE_DIR}/dNet"
"${PROJECT_SOURCE_DIR}/dWeb"
"${PROJECT_SOURCE_DIR}/dServer"
"${PROJECT_SOURCE_DIR}/thirdparty"
"${PROJECT_SOURCE_DIR}/thirdparty/nlohmann"
"${PROJECT_SOURCE_DIR}/dDashboardServer/auth"
)
target_link_libraries(DashboardAuth PRIVATE ${COMMON_LIBRARIES} dWeb dServer bcrypt OpenSSL::Crypto)

View File

@@ -0,0 +1,68 @@
#include "DashboardPacketHandler.h"
#include "BitStreamUtils.h"
#include "Logger.h"
#include "Game.h"
#include "handlers/MasterPacketHandler.h"
#include <functional>
#include <map>
namespace DashboardPacketHandler {
std::map<ServiceType, std::function<void()>> g_ServiceHandlers;
void DashboardNewIncomingConnection::Handle() {
LOG_DEBUG("DashboardPacketHandler: New incoming connection from %s", sysAddr.ToString(true));
}
void DashboardDisconnectionNotification::Handle() {
LOG_DEBUG("DashboardPacketHandler: Disconnection notification from %s", sysAddr.ToString(true));
}
void DashboardConnectionLost::Handle() {
LOG_DEBUG("DashboardPacketHandler: Connection lost with %s", sysAddr.ToString(true));
}
void DashboardConnectedPong::Handle() {
LOG_DEBUG("DashboardPacketHandler: Received pong from %s", sysAddr.ToString(true));
}
void DashboardUserPacketEnum::Handle() {
const auto it = g_ServiceHandlers.find(serviceType);
if (it != g_ServiceHandlers.end()) {
it->second();
} else {
LOG_DEBUG("DashboardPacketHandler: No handler registered for service type %u from %s", static_cast<uint16_t>(serviceType), sysAddr.ToString(true));
}
}
bool DashboardUserPacketEnum::Deserialize(RakNet::BitStream& bitStream) {
if (!PacketHandler::UserPacketEnum::Deserialize(bitStream)) {
return false;
}
VALIDATE_READ(bitStream.Read(serviceType));
return true;
}
void RegisterDashboardHandlers() {
// Override the default handlers with dashboard-specific implementations
PacketHandler::g_Handlers[ID_NEW_INCOMING_CONNECTION] = []() {
return std::make_unique<DashboardNewIncomingConnection>();
};
PacketHandler::g_Handlers[ID_DISCONNECTION_NOTIFICATION] = []() {
return std::make_unique<DashboardDisconnectionNotification>();
};
PacketHandler::g_Handlers[ID_CONNECTION_LOST] = []() {
return std::make_unique<DashboardConnectionLost>();
};
PacketHandler::g_Handlers[ID_CONNECTED_PONG] = []() {
return std::make_unique<DashboardConnectedPong>();
};
PacketHandler::g_Handlers[ID_USER_PACKET_ENUM] = []() {
return std::make_unique<DashboardUserPacketEnum>();
};
// Register service type handlers
}
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include "PacketHandler.h"
#include "ServiceType.h"
namespace DashboardPacketHandler {
// Dashboard-specific implementations of RakNet packet handlers
struct DashboardNewIncomingConnection : public PacketHandler::NewIncomingConnection {
void Handle() override;
};
struct DashboardDisconnectionNotification : public PacketHandler::DisconnectionNotification {
void Handle() override;
};
struct DashboardConnectionLost : public PacketHandler::ConnectionLost {
void Handle() override;
};
struct DashboardConnectedPong : public PacketHandler::ConnectedPong {
void Handle() override;
};
struct DashboardUserPacketEnum : public PacketHandler::UserPacketEnum {
ServiceType serviceType{};
bool Deserialize(RakNet::BitStream& bitStream);
void Handle() override;
};
// Initialize dashboard-specific packet handlers
void RegisterDashboardHandlers();
}

View File

@@ -5,30 +5,27 @@
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
#include "RakNetTypes.h" #include "RakNetTypes.h"
#include "routes/ServerState.h" #include "ServerState.h"
#include <chrono> #include <chrono>
#include <mutex>
namespace MasterPacketHandler { namespace MasterPacketHandler {
namespace { std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers = {
std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers = { {MessageType::Master::SERVER_INFO, []() {
{MessageType::Master::SERVER_INFO, []() { return std::make_unique<ServerInfo>();
return std::make_unique<ServerInfo>(); }},
}}, {MessageType::Master::PLAYER_ADDED, []() {
{MessageType::Master::PLAYER_ADDED, []() { return std::make_unique<PlayerAdded>();
return std::make_unique<PlayerAdded>(); }},
}}, {MessageType::Master::PLAYER_REMOVED, []() {
{MessageType::Master::PLAYER_REMOVED, []() { return std::make_unique<PlayerRemoved>();
return std::make_unique<PlayerRemoved>(); }},
}}, {MessageType::Master::SHUTDOWN_RESPONSE, []() {
{MessageType::Master::SHUTDOWN_RESPONSE, []() { return std::make_unique<ShutdownResponse>();
return std::make_unique<ShutdownResponse>(); }},
}}, {MessageType::Master::SHUTDOWN, []() {
{MessageType::Master::SHUTDOWN, []() { return std::make_unique<Shutdown>();
return std::make_unique<Shutdown>(); }},
}}, };
};
}
bool ServerInfo::Deserialize(RakNet::BitStream& bitStream) { bool ServerInfo::Deserialize(RakNet::BitStream& bitStream) {
VALIDATE_READ(bitStream.Read(port)); VALIDATE_READ(bitStream.Read(port));
@@ -42,8 +39,6 @@ namespace MasterPacketHandler {
} }
void ServerInfo::Handle() { void ServerInfo::Handle() {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
LOG("MasterPacketHandler: Processing SERVER_INFO for service type %i, zone %u, instance %u, port %u", serverType, zoneID, instanceID, port); LOG("MasterPacketHandler: Processing SERVER_INFO for service type %i, zone %u, instance %u, port %u", serverType, zoneID, instanceID, port);
switch (serverType) { switch (serverType) {
@@ -94,7 +89,6 @@ namespace MasterPacketHandler {
} }
void PlayerAdded::Handle() { void PlayerAdded::Handle() {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
for (auto& world : ServerState::g_WorldInstances) { for (auto& world : ServerState::g_WorldInstances) {
if (world.mapID == zoneID && world.instanceID == instanceID) { if (world.mapID == zoneID && world.instanceID == instanceID) {
world.players++; world.players++;
@@ -111,7 +105,6 @@ namespace MasterPacketHandler {
} }
void PlayerRemoved::Handle() { void PlayerRemoved::Handle() {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
for (auto& world : ServerState::g_WorldInstances) { for (auto& world : ServerState::g_WorldInstances) {
if (world.mapID == zoneID && world.instanceID == instanceID) { if (world.mapID == zoneID && world.instanceID == instanceID) {
if (world.players > 0) world.players--; if (world.players > 0) world.players--;
@@ -129,8 +122,6 @@ namespace MasterPacketHandler {
} }
void ShutdownResponse::Handle() { void ShutdownResponse::Handle() {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
switch (serverType) { switch (serverType) {
case ServiceType::AUTH: case ServiceType::AUTH:
ServerState::g_AuthStatus.online = false; ServerState::g_AuthStatus.online = false;
@@ -163,47 +154,4 @@ namespace MasterPacketHandler {
LOG("Received SHUTDOWN command from Master"); LOG("Received SHUTDOWN command from Master");
Game::lastSignal = -1; // Trigger shutdown Game::lastSignal = -1; // Trigger shutdown
} }
void HandleMasterPacket(Packet* packet) {
if (!packet) return;
switch (packet->data[0]) {
case ID_DISCONNECTION_NOTIFICATION:
case ID_CONNECTION_LOST:
LOG("Lost connection to Master Server");
{
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
ServerState::g_AuthStatus.online = false;
ServerState::g_ChatStatus.online = false;
ServerState::g_WorldInstances.clear();
}
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
LOG("Connected to Master Server");
break;
case ID_USER_PACKET_ENUM: {
RakNet::BitStream inStream(packet->data, packet->length, false);
uint64_t header{};
inStream.Read(header);
const auto packetType = static_cast<MessageType::Master>(header);
LOG_DEBUG("Received Master packet type: %i", packetType);
auto it = g_Handlers.find(packetType);
if (it != g_Handlers.end()) {
auto handler = it->second();
if (!handler->Deserialize(inStream)) {
LOG_DEBUG("Error deserializing Master packet type %i", packetType);
return;
}
handler->Handle();
} else {
LOG_DEBUG("Unhandled Master packet type: %i", packetType);
}
break;
}
default:
break;
}
}
} }

View File

@@ -1,4 +1,4 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <map> #include <map>
@@ -74,6 +74,6 @@ namespace MasterPacketHandler {
void Handle() override; void Handle() override;
}; };
// Main handler function // Master packet handler registry
void HandleMasterPacket(Packet* packet); extern std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers;
} }

View File

@@ -17,30 +17,7 @@ void RegisterAPIRoutes() {
.method = eHTTPMethod::GET, .method = eHTTPMethod::GET,
.middleware = { std::make_shared<RequireAuthMiddleware>(0) }, .middleware = { std::make_shared<RequireAuthMiddleware>(0) },
.handle = [](HTTPReply& reply, const HTTPContext& context) { .handle = [](HTTPReply& reply, const HTTPContext& context) {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex); nlohmann::json response = ServerState::GetServerStateJson();
nlohmann::json response = {
{"auth", {
{"online", ServerState::g_AuthStatus.online},
{"players", ServerState::g_AuthStatus.players},
{"version", ServerState::g_AuthStatus.version}
}},
{"chat", {
{"online", ServerState::g_ChatStatus.online},
{"players", ServerState::g_ChatStatus.players}
}},
{"worlds", nlohmann::json::array()}
};
for (const auto& world : ServerState::g_WorldInstances) {
response["worlds"].push_back({
{"mapID", world.mapID},
{"instanceID", world.instanceID},
{"cloneID", world.cloneID},
{"players", world.players},
{"isPrivate", world.isPrivate}
});
}
reply.status = eHTTPStatusCode::OK; reply.status = eHTTPStatusCode::OK;
reply.message = response.dump(); reply.message = response.dump();
@@ -92,10 +69,18 @@ void RegisterAPIRoutes() {
.method = eHTTPMethod::GET, .method = eHTTPMethod::GET,
.middleware = { std::make_shared<RequireAuthMiddleware>(0) }, .middleware = { std::make_shared<RequireAuthMiddleware>(0) },
.handle = [](HTTPReply& reply, const HTTPContext& context) { .handle = [](HTTPReply& reply, const HTTPContext& context) {
nlohmann::json response = {{"count", 0}, {"note", "Not yet implemented"}}; try {
reply.status = eHTTPStatusCode::OK; const uint32_t count = Database::Get()->GetCharacterCount();
reply.message = response.dump(); nlohmann::json response = {{"count", count}};
reply.contentType = eContentType::APPLICATION_JSON; reply.status = eHTTPStatusCode::OK;
reply.message = response.dump();
reply.contentType = eContentType::APPLICATION_JSON;
} catch (std::exception& ex) {
LOG("Error in /api/characters/count: %s", ex.what());
reply.status = eHTTPStatusCode::INTERNAL_SERVER_ERROR;
reply.message = "{\"error\":\"Database error\"}";
reply.contentType = eContentType::APPLICATION_JSON;
}
} }
}); });
} }

View File

@@ -0,0 +1,31 @@
set(DASHBOARDROUTES_SOURCES
"APIRoutes.cpp"
"StaticRoutes.cpp"
"DashboardRoutes.cpp"
"WSRoutes.cpp"
"AuthRoutes.cpp"
)
add_library(DashboardRoutes STATIC ${DASHBOARDROUTES_SOURCES})
target_include_directories(DashboardRoutes PRIVATE
"${PROJECT_SOURCE_DIR}/dCommon"
"${PROJECT_SOURCE_DIR}/dCommon/dClient"
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
"${PROJECT_SOURCE_DIR}/dDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/CDClientDatabase/CDClientTables"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/ITables"
"${PROJECT_SOURCE_DIR}/dDatabase/GameDatabase/MySQL"
"${PROJECT_SOURCE_DIR}/dNet"
"${PROJECT_SOURCE_DIR}/dWeb"
"${PROJECT_SOURCE_DIR}/dServer"
"${PROJECT_SOURCE_DIR}/thirdparty"
"${PROJECT_SOURCE_DIR}/thirdparty/nlohmann"
"${PROJECT_SOURCE_DIR}/dDashboardServer/auth"
"${PROJECT_SOURCE_DIR}/dDashboardServer/routes"
"${PROJECT_SOURCE_DIR}/dDashboardServer/handlers"
)
target_link_libraries(DashboardRoutes PRIVATE ${COMMON_LIBRARIES} dWeb dServer)

View File

@@ -25,35 +25,16 @@ void RegisterDashboardRoutes() {
env.set_lstrip_blocks(true); env.set_lstrip_blocks(true);
// Prepare data for template // Prepare data for template
nlohmann::json data; nlohmann::json data = context.GetUserDataJson();
// Get username from auth context
data["username"] = context.authenticatedUser;
data["gmLevel"] = context.gmLevel;
// Server status (placeholder data - will be updated with real data from master) // Server status - merge with server state
data["auth"]["online"] = ServerState::g_AuthStatus.online; nlohmann::json serverState = ServerState::GetServerStateJson();
data["auth"]["players"] = ServerState::g_AuthStatus.players; data.merge_patch(serverState);
data["chat"]["online"] = ServerState::g_ChatStatus.online;
data["chat"]["players"] = ServerState::g_ChatStatus.players;
// World instances
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
data["worlds"] = nlohmann::json::array();
for (const auto& world : ServerState::g_WorldInstances) {
data["worlds"].push_back({
{"mapID", world.mapID},
{"instanceID", world.instanceID},
{"cloneID", world.cloneID},
{"players", world.players},
{"isPrivate", world.isPrivate}
});
}
// Statistics // Statistics
const uint32_t accountCount = Database::Get()->GetAccountCount();
data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication
data["stats"]["totalAccounts"] = accountCount; data["stats"]["totalAccounts"] = Database::Get()->GetAccountCount();
data["stats"]["totalCharacters"] = 0; // TODO: Add GetCharacterCount to database interface data["stats"]["totalCharacters"] = Database::Get()->GetCharacterCount();
// Render template // Render template
const std::string html = env.render_file("index.jinja2", data); const std::string html = env.render_file("index.jinja2", data);
@@ -82,9 +63,8 @@ void RegisterDashboardRoutes() {
env.set_trim_blocks(true); env.set_trim_blocks(true);
env.set_lstrip_blocks(true); env.set_lstrip_blocks(true);
// Render template with empty username // Render template with empty user data (not authenticated)
nlohmann::json data; nlohmann::json data = context.GetUserDataJson();
data["username"] = "";
const std::string html = env.render_file("login.jinja2", data); const std::string html = env.render_file("login.jinja2", data);
reply.status = eHTTPStatusCode::OK; reply.status = eHTTPStatusCode::OK;

View File

@@ -1,3 +1,7 @@
#pragma once #pragma once
#include "json.hpp"
class HTTPContext;
void RegisterDashboardRoutes(); void RegisterDashboardRoutes();

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <chrono> #include <chrono>
#include <mutex>
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include "json.hpp"
struct ServerStatus { struct ServerStatus {
bool online{false}; bool online{false};
@@ -27,5 +27,26 @@ namespace ServerState {
extern ServerStatus g_AuthStatus; extern ServerStatus g_AuthStatus;
extern ServerStatus g_ChatStatus; extern ServerStatus g_ChatStatus;
extern std::vector<WorldInstanceInfo> g_WorldInstances; extern std::vector<WorldInstanceInfo> g_WorldInstances;
extern std::mutex g_StatusMutex;
// Helper function to get all server state as JSON
inline nlohmann::json GetServerStateJson() {
nlohmann::json data;
data["auth"]["online"] = g_AuthStatus.online;
data["auth"]["players"] = g_AuthStatus.players;
data["chat"]["online"] = g_ChatStatus.online;
data["chat"]["players"] = g_ChatStatus.players;
data["worlds"] = nlohmann::json::array();
for (const auto& world : g_WorldInstances) {
data["worlds"].push_back({
{"mapID", world.mapID},
{"instanceID", world.instanceID},
{"cloneID", world.cloneID},
{"players", world.players},
{"isPrivate", world.isPrivate}
});
}
return data;
}
} }

View File

@@ -18,37 +18,14 @@ void RegisterWSRoutes() {
} }
void BroadcastDashboardUpdate() { void BroadcastDashboardUpdate() {
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex); // Get server state data (auth, chat, worlds) - mutex is acquired internally
nlohmann::json data = ServerState::GetServerStateJson();
nlohmann::json data = {
{"auth", {
{"online", ServerState::g_AuthStatus.online},
{"players", ServerState::g_AuthStatus.players},
{"version", ServerState::g_AuthStatus.version}
}},
{"chat", {
{"online", ServerState::g_ChatStatus.online},
{"players", ServerState::g_ChatStatus.players}
}},
{"worlds", nlohmann::json::array()}
};
for (const auto& world : ServerState::g_WorldInstances) {
data["worlds"].push_back({
{"mapID", world.mapID},
{"instanceID", world.instanceID},
{"cloneID", world.cloneID},
{"players", world.players},
{"isPrivate", world.isPrivate}
});
}
// Add statistics // Add statistics
try { try {
const uint32_t accountCount = Database::Get()->GetAccountCount();
data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication
data["stats"]["totalAccounts"] = accountCount; data["stats"]["totalAccounts"] = Database::Get()->GetAccountCount();
data["stats"]["totalCharacters"] = 0; // TODO: Add GetCharacterCount to database interface data["stats"]["totalCharacters"] = Database::Get()->GetCharacterCount();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
LOG_DEBUG("Error getting stats: %s", ex.what()); LOG_DEBUG("Error getting stats: %s", ex.what());
} }

View File

@@ -20,9 +20,6 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#players">Players</a> <a class="nav-link" href="#players">Players</a>
</li> </li>
<li class="nav-item">
<a class="nav-link" href="#servers">Servers</a>
</li>
<li class="nav-item mt-auto"> <li class="nav-item mt-auto">
<a class="nav-link" href="#" id="logoutBtn">Logout</a> <a class="nav-link" href="#" id="logoutBtn">Logout</a>
</li> </li>

View File

@@ -33,6 +33,9 @@ public:
// Get the character ids for the given account. // Get the character ids for the given account.
virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0; virtual std::vector<LWOOBJID> GetAccountCharacterIds(const LWOOBJID accountId) = 0;
// Get the total number of characters in the database.
virtual uint32_t GetCharacterCount() = 0;
// Insert a new character into the database. // Insert a new character into the database.
virtual void InsertNewCharacter(const ICharInfo::Info info) = 0; virtual void InsertNewCharacter(const ICharInfo::Info info) = 0;

View File

@@ -126,6 +126,7 @@ public:
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override; void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
void DeleteUgcBuild(const LWOOBJID bigId) override; void DeleteUgcBuild(const LWOOBJID bigId) override;
uint32_t GetAccountCount() override; uint32_t GetAccountCount() override;
uint32_t GetCharacterCount() override;
void RecordFailedAttempt(const uint32_t accountId) override; void RecordFailedAttempt(const uint32_t accountId) override;
void ClearFailedAttempts(const uint32_t accountId) override; void ClearFailedAttempts(const uint32_t accountId) override;
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override; void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override;

View File

@@ -54,6 +54,11 @@ std::vector<LWOOBJID> MySQLDatabase::GetAccountCharacterIds(const LWOOBJID accou
return toReturn; return toReturn;
} }
uint32_t MySQLDatabase::GetCharacterCount() {
auto res = ExecuteSelect("SELECT COUNT(*) as count FROM charinfo;");
return res->next() ? res->getUInt("count") : 0;
}
void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) { void MySQLDatabase::InsertNewCharacter(const ICharInfo::Info info) {
ExecuteInsert( ExecuteInsert(
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`) VALUES (?,?,?,?,?,?)", "INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`) VALUES (?,?,?,?,?,?)",

View File

@@ -124,6 +124,7 @@ public:
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override; void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override;
void DeleteUgcBuild(const LWOOBJID bigId) override; void DeleteUgcBuild(const LWOOBJID bigId) override;
uint32_t GetAccountCount() override; uint32_t GetAccountCount() override;
uint32_t GetCharacterCount() override;
void RecordFailedAttempt(const uint32_t accountId) override; void RecordFailedAttempt(const uint32_t accountId) override;
void ClearFailedAttempts(const uint32_t accountId) override; void ClearFailedAttempts(const uint32_t accountId) override;
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override; void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override;

View File

@@ -55,6 +55,13 @@ std::vector<LWOOBJID> SQLiteDatabase::GetAccountCharacterIds(const LWOOBJID acco
return toReturn; return toReturn;
} }
uint32_t SQLiteDatabase::GetCharacterCount() {
auto [_, res] = ExecuteSelect("SELECT COUNT(*) as count FROM charinfo;");
if (res.eof()) return 0;
return res.getIntField("count");
}
void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) { void SQLiteDatabase::InsertNewCharacter(const ICharInfo::Info info) {
ExecuteInsert( ExecuteInsert(
"INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`, `prop_clone_id`) VALUES (?,?,?,?,?,?,(SELECT IFNULL(MAX(`prop_clone_id`), 0) + 1 FROM `charinfo`))", "INSERT INTO `charinfo`(`id`, `account_id`, `name`, `pending_name`, `needs_rename`, `last_login`, `prop_clone_id`) VALUES (?,?,?,?,?,?,(SELECT IFNULL(MAX(`prop_clone_id`), 0) + 1 FROM `charinfo`))",

View File

@@ -103,6 +103,7 @@ class TestSQLDatabase : public GameDatabase {
void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override {}; void InsertUgcBuild(const std::string& modules, const LWOOBJID bigId, const std::optional<LWOOBJID> characterId) override {};
void DeleteUgcBuild(const LWOOBJID bigId) override {}; void DeleteUgcBuild(const LWOOBJID bigId) override {};
uint32_t GetAccountCount() override { return 0; }; uint32_t GetAccountCount() override { return 0; };
uint32_t GetCharacterCount() override { return 0; };
void RecordFailedAttempt(const uint32_t accountId) override {}; void RecordFailedAttempt(const uint32_t accountId) override {};
void ClearFailedAttempts(const uint32_t accountId) override {}; void ClearFailedAttempts(const uint32_t accountId) override {};
void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override {}; void SetLockout(const uint32_t accountId, const int64_t lockoutUntil) override {};

View File

@@ -6,6 +6,7 @@ set(DNET_SOURCES "AuthPackets.cpp"
"MailInfo.cpp" "MailInfo.cpp"
"MasterPackets.cpp" "MasterPackets.cpp"
"PacketUtils.cpp" "PacketUtils.cpp"
"PacketHandler.cpp"
"WorldPackets.cpp" "WorldPackets.cpp"
"ZoneInstanceManager.cpp") "ZoneInstanceManager.cpp")

130
dNet/PacketHandler.cpp Normal file
View File

@@ -0,0 +1,130 @@
#include "PacketHandler.h"
#include "BitStream.h"
#include "DluAssert.h"
#include <map>
#include <functional>
#include <cstdio>
void RaknetPacket::Serialize(RakNet::BitStream& bitStream) const {
bitStream.Write<uint8_t>(static_cast<uint8_t>(messageID));
}
bool RaknetPacket::Deserialize(RakNet::BitStream& bitStream) {
uint8_t id;
if (!bitStream.Read<uint8_t>(id)) {
return false;
}
messageID = static_cast<DefaultMessageIDTypes>(id);
return true;
}
namespace PacketHandler {
std::map<DefaultMessageIDTypes, std::function<std::unique_ptr<RaknetPacket>()>> g_Handlers = {
{ID_INTERNAL_PING, []() { return std::make_unique<InternalPing>(); }},
{ID_PING, []() { return std::make_unique<Ping>(); }},
{ID_PING_OPEN_CONNECTIONS, []() { return std::make_unique<PingOpenConnections>(); }},
{ID_CONNECTED_PONG, []() { return std::make_unique<ConnectedPong>(); }},
{ID_CONNECTION_REQUEST, []() { return std::make_unique<ConnectionRequest>(); }},
{ID_SECURED_CONNECTION_RESPONSE, []() { return std::make_unique<SecuredConnectionResponse>(); }},
{ID_SECURED_CONNECTION_CONFIRMATION, []() { return std::make_unique<SecuredConnectionConfirmation>(); }},
{ID_RPC_MAPPING, []() { return std::make_unique<RPCMapping>(); }},
{ID_DETECT_LOST_CONNECTIONS, []() { return std::make_unique<DetectLostConnections>(); }},
{ID_OPEN_CONNECTION_REQUEST, []() { return std::make_unique<OpenConnectionRequest>(); }},
{ID_OPEN_CONNECTION_REPLY, []() { return std::make_unique<OpenConnectionReply>(); }},
{ID_RPC, []() { return std::make_unique<RPC>(); }},
{ID_RPC_REPLY, []() { return std::make_unique<RPCReply>(); }},
{ID_OUT_OF_BAND_INTERNAL, []() { return std::make_unique<OutOfBandInternal>(); }},
{ID_CONNECTION_REQUEST_ACCEPTED, []() { return std::make_unique<ConnectionRequestAccepted>(); }},
{ID_CONNECTION_ATTEMPT_FAILED, []() { return std::make_unique<ConnectionAttemptFailed>(); }},
{ID_ALREADY_CONNECTED, []() { return std::make_unique<AlreadyConnected>(); }},
{ID_NEW_INCOMING_CONNECTION, []() { return std::make_unique<NewIncomingConnection>(); }},
{ID_NO_FREE_INCOMING_CONNECTIONS, []() { return std::make_unique<NoFreeIncomingConnections>(); }},
{ID_DISCONNECTION_NOTIFICATION, []() { return std::make_unique<DisconnectionNotification>(); }},
{ID_CONNECTION_LOST, []() { return std::make_unique<ConnectionLost>(); }},
{ID_RSA_PUBLIC_KEY_MISMATCH, []() { return std::make_unique<RSAPublicKeyMismatch>(); }},
{ID_CONNECTION_BANNED, []() { return std::make_unique<ConnectionBanned>(); }},
{ID_INVALID_PASSWORD, []() { return std::make_unique<InvalidPassword>(); }},
{ID_MODIFIED_PACKET, []() { return std::make_unique<ModifiedPacket>(); }},
{ID_TIMESTAMP, []() { return std::make_unique<Timestamp>(); }},
{ID_PONG, []() { return std::make_unique<Pong>(); }},
{ID_ADVERTISE_SYSTEM, []() { return std::make_unique<AdvertiseSystem>(); }},
{ID_REMOTE_DISCONNECTION_NOTIFICATION, []() { return std::make_unique<RemoteDisconnectionNotification>(); }},
{ID_REMOTE_CONNECTION_LOST, []() { return std::make_unique<RemoteConnectionLost>(); }},
{ID_REMOTE_NEW_INCOMING_CONNECTION, []() { return std::make_unique<RemoteNewIncomingConnection>(); }},
{ID_DOWNLOAD_PROGRESS, []() { return std::make_unique<DownloadProgress>(); }},
{ID_FILE_LIST_TRANSFER_HEADER, []() { return std::make_unique<FileListTransferHeader>(); }},
{ID_FILE_LIST_TRANSFER_FILE, []() { return std::make_unique<FileListTransferFile>(); }},
{ID_DDT_DOWNLOAD_REQUEST, []() { return std::make_unique<DDTDownloadRequest>(); }},
{ID_TRANSPORT_STRING, []() { return std::make_unique<TransportString>(); }},
{ID_REPLICA_MANAGER_CONSTRUCTION, []() { return std::make_unique<ReplicaManagerConstruction>(); }},
{ID_REPLICA_MANAGER_DESTRUCTION, []() { return std::make_unique<ReplicaManagerDestruction>(); }},
{ID_REPLICA_MANAGER_SCOPE_CHANGE, []() { return std::make_unique<ReplicaManagerScopeChange>(); }},
{ID_REPLICA_MANAGER_SERIALIZE, []() { return std::make_unique<ReplicaManagerSerialize>(); }},
{ID_REPLICA_MANAGER_DOWNLOAD_STARTED, []() { return std::make_unique<ReplicaManagerDownloadStarted>(); }},
{ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE, []() { return std::make_unique<ReplicaManagerDownloadComplete>(); }},
{ID_CONNECTION_GRAPH_REQUEST, []() { return std::make_unique<ConnectionGraphRequest>(); }},
{ID_CONNECTION_GRAPH_REPLY, []() { return std::make_unique<ConnectionGraphReply>(); }},
{ID_CONNECTION_GRAPH_UPDATE, []() { return std::make_unique<ConnectionGraphUpdate>(); }},
{ID_CONNECTION_GRAPH_NEW_CONNECTION, []() { return std::make_unique<ConnectionGraphNewConnection>(); }},
{ID_CONNECTION_GRAPH_CONNECTION_LOST, []() { return std::make_unique<ConnectionGraphConnectionLost>(); }},
{ID_CONNECTION_GRAPH_DISCONNECTION_NOTIFICATION, []() { return std::make_unique<ConnectionGraphDisconnectionNotification>(); }},
{ID_ROUTE_AND_MULTICAST, []() { return std::make_unique<RouteAndMulticast>(); }},
{ID_RAKVOICE_OPEN_CHANNEL_REQUEST, []() { return std::make_unique<RakVoiceOpenChannelRequest>(); }},
{ID_RAKVOICE_OPEN_CHANNEL_REPLY, []() { return std::make_unique<RakVoiceOpenChannelReply>(); }},
{ID_RAKVOICE_CLOSE_CHANNEL, []() { return std::make_unique<RakVoiceCloseChannel>(); }},
{ID_RAKVOICE_DATA, []() { return std::make_unique<RakVoiceData>(); }},
{ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE, []() { return std::make_unique<AutopatcherGetChangelistSinceDate>(); }},
{ID_AUTOPATCHER_CREATION_LIST, []() { return std::make_unique<AutopatcherCreationList>(); }},
{ID_AUTOPATCHER_DELETION_LIST, []() { return std::make_unique<AutopatcherDeletionList>(); }},
{ID_AUTOPATCHER_GET_PATCH, []() { return std::make_unique<AutopatcherGetPatch>(); }},
{ID_AUTOPATCHER_PATCH_LIST, []() { return std::make_unique<AutopatcherPatchList>(); }},
{ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR, []() { return std::make_unique<AutopatcherRepositoryFatalError>(); }},
{ID_AUTOPATCHER_FINISHED_INTERNAL, []() { return std::make_unique<AutopatcherFinishedInternal>(); }},
{ID_AUTOPATCHER_FINISHED, []() { return std::make_unique<AutopatcherFinished>(); }},
{ID_AUTOPATCHER_RESTART_APPLICATION, []() { return std::make_unique<AutopatcherRestartApplication>(); }},
{ID_NAT_PUNCHTHROUGH_REQUEST, []() { return std::make_unique<NATpunchtroughRequest>(); }},
{ID_NAT_TARGET_NOT_CONNECTED, []() { return std::make_unique<NATTargetNotConnected>(); }},
{ID_NAT_TARGET_CONNECTION_LOST, []() { return std::make_unique<NATTargetConnectionLost>(); }},
{ID_NAT_CONNECT_AT_TIME, []() { return std::make_unique<NATConnectAtTime>(); }},
{ID_NAT_SEND_OFFLINE_MESSAGE_AT_TIME, []() { return std::make_unique<NATSendOfflineMessageAtTime>(); }},
{ID_NAT_IN_PROGRESS, []() { return std::make_unique<NATInProgress>(); }},
{ID_DATABASE_QUERY_REQUEST, []() { return std::make_unique<DatabaseQueryRequest>(); }},
{ID_DATABASE_UPDATE_ROW, []() { return std::make_unique<DatabaseUpdateRow>(); }},
{ID_DATABASE_REMOVE_ROW, []() { return std::make_unique<DatabaseRemoveRow>(); }},
{ID_DATABASE_QUERY_REPLY, []() { return std::make_unique<DatabaseQueryReply>(); }},
{ID_DATABASE_UNKNOWN_TABLE, []() { return std::make_unique<DatabaseUnknownTable>(); }},
{ID_DATABASE_INCORRECT_PASSWORD, []() { return std::make_unique<DatabaseIncorrectPassword>(); }},
{ID_READY_EVENT_SET, []() { return std::make_unique<ReadyEventSet>(); }},
{ID_READY_EVENT_UNSET, []() { return std::make_unique<ReadyEventUnset>(); }},
{ID_READY_EVENT_ALL_SET, []() { return std::make_unique<ReadyEventAllSet>(); }},
{ID_READY_EVENT_QUERY, []() { return std::make_unique<ReadyEventQuery>(); }},
{ID_LOBBY_GENERAL, []() { return std::make_unique<LobbyGeneral>(); }},
{ID_AUTO_RPC_CALL, []() { return std::make_unique<AutoRPCCall>(); }},
{ID_AUTO_RPC_REMOTE_INDEX, []() { return std::make_unique<AutoRPCRemoteIndex>(); }},
{ID_AUTO_RPC_UNKNOWN_REMOTE_INDEX, []() { return std::make_unique<AutoRPCUnknownRemoteIndex>(); }},
{ID_RPC_REMOTE_ERROR, []() { return std::make_unique<RPCRemoteError>(); }},
{ID_USER_PACKET_ENUM, []() { return std::make_unique<UserPacketEnum>(); }},
};
void HandlePacket(RakNet::BitStream& inStream, const SystemAddress& sysAddr) {
RaknetPacket data;
if (!data.Deserialize(inStream)) {
fprintf(stderr, "Error reading packet header\n");
return;
}
auto it = g_Handlers.find(data.messageID);
if (it != g_Handlers.end()) {
auto packet = it->second();
packet->sysAddr = sysAddr;
if (!packet->Deserialize(inStream)) {
fprintf(stderr, "Error reading packet data for message ID: %i\n", data.messageID);
return;
}
packet->Handle();
} else {
fprintf(stderr, "Unhandled packet with ID: %i\n", data.messageID);
}
}
}

456
dNet/PacketHandler.h Normal file
View File

@@ -0,0 +1,456 @@
#ifndef __RaknetPacket_H__
#define __RaknetPacket_H__
#include <cstdint>
#include <memory>
#include <functional>
#include <map>
#include "MessageIdentifiers.h"
#include <RakNetTypes.h>
struct Packet;
namespace RakNet {
class BitStream;
}
struct RaknetPacket {
DefaultMessageIDTypes messageID = static_cast<DefaultMessageIDTypes>(-1);
SystemAddress sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
RaknetPacket() = default;
RaknetPacket(DefaultMessageIDTypes _messageID) : messageID{_messageID} {};
void Serialize(RakNet::BitStream& bitStream) const;
bool Deserialize(RakNet::BitStream& bitStream);
virtual ~RaknetPacket() = default;
virtual void Handle() {};
};
namespace PacketHandler {
struct InternalPing : public RaknetPacket {
void Handle() override {};
InternalPing() : RaknetPacket(ID_INTERNAL_PING) {}
};
struct Ping : public RaknetPacket {
void Handle() override {};
Ping() : RaknetPacket(ID_PING) {}
};
struct PingOpenConnections : public RaknetPacket {
void Handle() override {};
PingOpenConnections() : RaknetPacket(ID_PING_OPEN_CONNECTIONS) {}
};
struct ConnectedPong : public RaknetPacket {
void Handle() override {};
ConnectedPong() : RaknetPacket(ID_CONNECTED_PONG) {}
};
struct ConnectionRequest : public RaknetPacket {
void Handle() override {};
ConnectionRequest() : RaknetPacket(ID_CONNECTION_REQUEST) {}
};
struct SecuredConnectionResponse : public RaknetPacket {
void Handle() override {};
SecuredConnectionResponse() : RaknetPacket(ID_SECURED_CONNECTION_RESPONSE) {}
};
struct SecuredConnectionConfirmation : public RaknetPacket {
void Handle() override {};
SecuredConnectionConfirmation() : RaknetPacket(ID_SECURED_CONNECTION_CONFIRMATION) {}
};
struct RPCMapping : public RaknetPacket {
void Handle() override {};
RPCMapping() : RaknetPacket(ID_RPC_MAPPING) {}
};
struct DetectLostConnections : public RaknetPacket {
void Handle() override {};
DetectLostConnections() : RaknetPacket(ID_DETECT_LOST_CONNECTIONS) {}
};
struct OpenConnectionRequest : public RaknetPacket {
void Handle() override {};
OpenConnectionRequest() : RaknetPacket(ID_OPEN_CONNECTION_REQUEST) {}
};
struct OpenConnectionReply : public RaknetPacket {
void Handle() override {};
OpenConnectionReply() : RaknetPacket(ID_OPEN_CONNECTION_REPLY) {}
};
struct RPC : public RaknetPacket {
void Handle() override {};
RPC() : RaknetPacket(ID_RPC) {}
};
struct RPCReply : public RaknetPacket {
void Handle() override {};
RPCReply() : RaknetPacket(ID_RPC_REPLY) {}
};
struct OutOfBandInternal : public RaknetPacket {
void Handle() override {};
OutOfBandInternal() : RaknetPacket(ID_OUT_OF_BAND_INTERNAL) {}
};
struct ConnectionRequestAccepted : public RaknetPacket {
void Handle() override {};
ConnectionRequestAccepted() : RaknetPacket(ID_CONNECTION_REQUEST_ACCEPTED) {}
};
struct ConnectionAttemptFailed : public RaknetPacket {
void Handle() override {};
ConnectionAttemptFailed() : RaknetPacket(ID_CONNECTION_ATTEMPT_FAILED) {}
};
struct AlreadyConnected : public RaknetPacket {
void Handle() override {};
AlreadyConnected() : RaknetPacket(ID_ALREADY_CONNECTED) {}
};
struct NewIncomingConnection : public RaknetPacket {
void Handle() override {};
NewIncomingConnection() : RaknetPacket(ID_NEW_INCOMING_CONNECTION) {}
};
struct NoFreeIncomingConnections : public RaknetPacket {
void Handle() override {};
NoFreeIncomingConnections() : RaknetPacket(ID_NO_FREE_INCOMING_CONNECTIONS) {}
};
struct DisconnectionNotification : public RaknetPacket {
void Handle() override {};
DisconnectionNotification() : RaknetPacket(ID_DISCONNECTION_NOTIFICATION) {}
};
struct ConnectionLost : public RaknetPacket {
void Handle() override {};
ConnectionLost() : RaknetPacket(ID_CONNECTION_LOST) {}
};
struct RSAPublicKeyMismatch : public RaknetPacket {
void Handle() override {};
RSAPublicKeyMismatch() : RaknetPacket(ID_RSA_PUBLIC_KEY_MISMATCH) {}
};
struct ConnectionBanned : public RaknetPacket {
void Handle() override {};
ConnectionBanned() : RaknetPacket(ID_CONNECTION_BANNED) {}
};
struct InvalidPassword : public RaknetPacket {
void Handle() override {};
InvalidPassword() : RaknetPacket(ID_INVALID_PASSWORD) {}
};
struct ModifiedPacket : public RaknetPacket {
void Handle() override {};
ModifiedPacket() : RaknetPacket(ID_MODIFIED_PACKET) {}
};
struct Timestamp : public RaknetPacket {
void Handle() override {};
Timestamp() : RaknetPacket(ID_TIMESTAMP) {}
};
struct Pong : public RaknetPacket {
void Handle() override {};
Pong() : RaknetPacket(ID_PONG) {}
};
struct AdvertiseSystem : public RaknetPacket {
void Handle() override {};
AdvertiseSystem() : RaknetPacket(ID_ADVERTISE_SYSTEM) {}
};
struct RemoteDisconnectionNotification : public RaknetPacket {
void Handle() override {};
RemoteDisconnectionNotification() : RaknetPacket(ID_REMOTE_DISCONNECTION_NOTIFICATION) {}
};
struct RemoteConnectionLost : public RaknetPacket {
void Handle() override {};
RemoteConnectionLost() : RaknetPacket(ID_REMOTE_CONNECTION_LOST) {}
};
struct RemoteNewIncomingConnection : public RaknetPacket {
void Handle() override {};
RemoteNewIncomingConnection() : RaknetPacket(ID_REMOTE_NEW_INCOMING_CONNECTION) {}
};
struct DownloadProgress : public RaknetPacket {
void Handle() override {};
DownloadProgress() : RaknetPacket(ID_DOWNLOAD_PROGRESS) {}
};
struct FileListTransferHeader : public RaknetPacket {
void Handle() override {};
FileListTransferHeader() : RaknetPacket(ID_FILE_LIST_TRANSFER_HEADER) {}
};
struct FileListTransferFile : public RaknetPacket {
void Handle() override {};
FileListTransferFile() : RaknetPacket(ID_FILE_LIST_TRANSFER_FILE) {}
};
struct DDTDownloadRequest : public RaknetPacket {
void Handle() override {};
DDTDownloadRequest() : RaknetPacket(ID_DDT_DOWNLOAD_REQUEST) {}
};
struct TransportString : public RaknetPacket {
void Handle() override {};
TransportString() : RaknetPacket(ID_TRANSPORT_STRING) {}
};
struct ReplicaManagerConstruction : public RaknetPacket {
void Handle() override {};
ReplicaManagerConstruction() : RaknetPacket(ID_REPLICA_MANAGER_CONSTRUCTION) {}
};
struct ReplicaManagerDestruction : public RaknetPacket {
void Handle() override {};
ReplicaManagerDestruction() : RaknetPacket(ID_REPLICA_MANAGER_DESTRUCTION) {}
};
struct ReplicaManagerScopeChange : public RaknetPacket {
void Handle() override {};
ReplicaManagerScopeChange() : RaknetPacket(ID_REPLICA_MANAGER_SCOPE_CHANGE) {}
};
struct ReplicaManagerSerialize : public RaknetPacket {
void Handle() override {};
ReplicaManagerSerialize() : RaknetPacket(ID_REPLICA_MANAGER_SERIALIZE) {}
};
struct ReplicaManagerDownloadStarted : public RaknetPacket {
void Handle() override {};
ReplicaManagerDownloadStarted() : RaknetPacket(ID_REPLICA_MANAGER_DOWNLOAD_STARTED) {}
};
struct ReplicaManagerDownloadComplete : public RaknetPacket {
void Handle() override {};
ReplicaManagerDownloadComplete() : RaknetPacket(ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE) {}
};
struct ConnectionGraphRequest : public RaknetPacket {
void Handle() override {};
ConnectionGraphRequest() : RaknetPacket(ID_CONNECTION_GRAPH_REQUEST) {}
};
struct ConnectionGraphReply : public RaknetPacket {
void Handle() override {};
ConnectionGraphReply() : RaknetPacket(ID_CONNECTION_GRAPH_REPLY) {}
};
struct ConnectionGraphUpdate : public RaknetPacket {
void Handle() override {};
ConnectionGraphUpdate() : RaknetPacket(ID_CONNECTION_GRAPH_UPDATE) {}
};
struct ConnectionGraphNewConnection : public RaknetPacket {
void Handle() override {};
ConnectionGraphNewConnection() : RaknetPacket(ID_CONNECTION_GRAPH_NEW_CONNECTION) {}
};
struct ConnectionGraphConnectionLost : public RaknetPacket {
void Handle() override {};
ConnectionGraphConnectionLost() : RaknetPacket(ID_CONNECTION_GRAPH_CONNECTION_LOST) {}
};
struct ConnectionGraphDisconnectionNotification : public RaknetPacket {
void Handle() override {};
ConnectionGraphDisconnectionNotification() : RaknetPacket(ID_CONNECTION_GRAPH_DISCONNECTION_NOTIFICATION) {}
};
struct RouteAndMulticast : public RaknetPacket {
void Handle() override {};
RouteAndMulticast() : RaknetPacket(ID_ROUTE_AND_MULTICAST) {}
};
struct RakVoiceOpenChannelRequest : public RaknetPacket {
void Handle() override {};
RakVoiceOpenChannelRequest() : RaknetPacket(ID_RAKVOICE_OPEN_CHANNEL_REQUEST) {}
};
struct RakVoiceOpenChannelReply : public RaknetPacket {
void Handle() override {};
RakVoiceOpenChannelReply() : RaknetPacket(ID_RAKVOICE_OPEN_CHANNEL_REPLY) {}
};
struct RakVoiceCloseChannel : public RaknetPacket {
void Handle() override {};
RakVoiceCloseChannel() : RaknetPacket(ID_RAKVOICE_CLOSE_CHANNEL) {}
};
struct RakVoiceData : public RaknetPacket {
void Handle() override {};
RakVoiceData() : RaknetPacket(ID_RAKVOICE_DATA) {}
};
struct AutopatcherGetChangelistSinceDate : public RaknetPacket {
void Handle() override {};
AutopatcherGetChangelistSinceDate() : RaknetPacket(ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE) {}
};
struct AutopatcherCreationList : public RaknetPacket {
void Handle() override {};
AutopatcherCreationList() : RaknetPacket(ID_AUTOPATCHER_CREATION_LIST) {}
};
struct AutopatcherDeletionList : public RaknetPacket {
void Handle() override {};
AutopatcherDeletionList() : RaknetPacket(ID_AUTOPATCHER_DELETION_LIST) {}
};
struct AutopatcherGetPatch : public RaknetPacket {
void Handle() override {};
AutopatcherGetPatch() : RaknetPacket(ID_AUTOPATCHER_GET_PATCH) {}
};
struct AutopatcherPatchList : public RaknetPacket {
void Handle() override {};
AutopatcherPatchList() : RaknetPacket(ID_AUTOPATCHER_PATCH_LIST) {}
};
struct AutopatcherRepositoryFatalError : public RaknetPacket {
void Handle() override {};
AutopatcherRepositoryFatalError() : RaknetPacket(ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR) {}
};
struct AutopatcherFinishedInternal : public RaknetPacket {
void Handle() override {};
AutopatcherFinishedInternal() : RaknetPacket(ID_AUTOPATCHER_FINISHED_INTERNAL) {}
};
struct AutopatcherFinished : public RaknetPacket {
void Handle() override {};
AutopatcherFinished() : RaknetPacket(ID_AUTOPATCHER_FINISHED) {}
};
struct AutopatcherRestartApplication : public RaknetPacket {
void Handle() override {};
AutopatcherRestartApplication() : RaknetPacket(ID_AUTOPATCHER_RESTART_APPLICATION) {}
};
struct NATpunchtroughRequest : public RaknetPacket {
void Handle() override {};
NATpunchtroughRequest() : RaknetPacket(ID_NAT_PUNCHTHROUGH_REQUEST) {}
};
struct NATTargetNotConnected : public RaknetPacket {
void Handle() override {};
NATTargetNotConnected() : RaknetPacket(ID_NAT_TARGET_NOT_CONNECTED) {}
};
struct NATTargetConnectionLost : public RaknetPacket {
void Handle() override {};
NATTargetConnectionLost() : RaknetPacket(ID_NAT_TARGET_CONNECTION_LOST) {}
};
struct NATConnectAtTime : public RaknetPacket {
void Handle() override {};
NATConnectAtTime() : RaknetPacket(ID_NAT_CONNECT_AT_TIME) {}
};
struct NATSendOfflineMessageAtTime : public RaknetPacket {
void Handle() override {};
NATSendOfflineMessageAtTime() : RaknetPacket(ID_NAT_SEND_OFFLINE_MESSAGE_AT_TIME) {}
};
struct NATInProgress : public RaknetPacket {
void Handle() override {};
NATInProgress() : RaknetPacket(ID_NAT_IN_PROGRESS) {}
};
struct DatabaseQueryRequest : public RaknetPacket {
void Handle() override {};
DatabaseQueryRequest() : RaknetPacket(ID_DATABASE_QUERY_REQUEST) {}
};
struct DatabaseUpdateRow : public RaknetPacket {
void Handle() override {};
DatabaseUpdateRow() : RaknetPacket(ID_DATABASE_UPDATE_ROW) {}
};
struct DatabaseRemoveRow : public RaknetPacket {
void Handle() override {};
DatabaseRemoveRow() : RaknetPacket(ID_DATABASE_REMOVE_ROW) {}
};
struct DatabaseQueryReply : public RaknetPacket {
void Handle() override {};
DatabaseQueryReply() : RaknetPacket(ID_DATABASE_QUERY_REPLY) {}
};
struct DatabaseUnknownTable : public RaknetPacket {
void Handle() override {};
DatabaseUnknownTable() : RaknetPacket(ID_DATABASE_UNKNOWN_TABLE) {}
};
struct DatabaseIncorrectPassword : public RaknetPacket {
void Handle() override {};
DatabaseIncorrectPassword() : RaknetPacket(ID_DATABASE_INCORRECT_PASSWORD) {}
};
struct ReadyEventSet : public RaknetPacket {
void Handle() override {};
ReadyEventSet() : RaknetPacket(ID_READY_EVENT_SET) {}
};
struct ReadyEventUnset : public RaknetPacket {
void Handle() override {};
ReadyEventUnset() : RaknetPacket(ID_READY_EVENT_UNSET) {}
};
struct ReadyEventAllSet : public RaknetPacket {
void Handle() override {};
ReadyEventAllSet() : RaknetPacket(ID_READY_EVENT_ALL_SET) {}
};
struct ReadyEventQuery : public RaknetPacket {
void Handle() override {};
ReadyEventQuery() : RaknetPacket(ID_READY_EVENT_QUERY) {}
};
struct LobbyGeneral : public RaknetPacket {
void Handle() override {};
LobbyGeneral() : RaknetPacket(ID_LOBBY_GENERAL) {}
};
struct AutoRPCCall : public RaknetPacket {
void Handle() override {};
AutoRPCCall() : RaknetPacket(ID_AUTO_RPC_CALL) {}
};
struct AutoRPCRemoteIndex : public RaknetPacket {
void Handle() override {};
AutoRPCRemoteIndex() : RaknetPacket(ID_AUTO_RPC_REMOTE_INDEX) {}
};
struct AutoRPCUnknownRemoteIndex : public RaknetPacket {
void Handle() override {};
AutoRPCUnknownRemoteIndex() : RaknetPacket(ID_AUTO_RPC_UNKNOWN_REMOTE_INDEX) {}
};
struct RPCRemoteError : public RaknetPacket {
void Handle() override {};
RPCRemoteError() : RaknetPacket(ID_RPC_REMOTE_ERROR) {}
};
struct UserPacketEnum : public RaknetPacket {
void Handle() override {};
UserPacketEnum() : RaknetPacket(ID_USER_PACKET_ENUM) {}
};
extern std::map<DefaultMessageIDTypes, std::function<std::unique_ptr<RaknetPacket>()>> g_Handlers;
void HandlePacket(RakNet::BitStream& inStream, const SystemAddress& sysAddr);
}
#endif // __RaknetPacket_H__

View File

@@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include "eHTTPStatusCode.h" #include "eHTTPStatusCode.h"
#include "json.hpp"
/** /**
* HTTP Request Context * HTTP Request Context
@@ -56,4 +57,14 @@ struct HTTPContext {
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower); std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), ::tolower);
headers[lowerName] = value; headers[lowerName] = value;
} }
/**
* Get user data as JSON for template rendering
*/
nlohmann::json GetUserDataJson() const {
nlohmann::json userData;
userData["username"] = authenticatedUser;
userData["gmLevel"] = gmLevel;
return userData;
}
}; };