mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-02-26 20:59:48 +00:00
WIP
This commit is contained in:
@@ -1,17 +1,12 @@
|
||||
set(DDASHBOARDSERVER_SOURCES
|
||||
"DashboardServer.cpp"
|
||||
"MasterPacketHandler.cpp"
|
||||
"routes/APIRoutes.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"
|
||||
"handlers/MasterPacketHandler.cpp"
|
||||
"handlers/DashboardPacketHandler.cpp"
|
||||
)
|
||||
|
||||
add_subdirectory(routes)
|
||||
add_subdirectory(auth)
|
||||
|
||||
add_executable(DashboardServer ${DDASHBOARDSERVER_SOURCES})
|
||||
|
||||
target_include_directories(DashboardServer PRIVATE
|
||||
@@ -29,11 +24,12 @@ target_include_directories(DashboardServer PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dServer"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/nlohmann"
|
||||
"${PROJECT_SOURCE_DIR}/dDashboardServer"
|
||||
"${PROJECT_SOURCE_DIR}/dDashboardServer/auth"
|
||||
"${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)
|
||||
|
||||
@@ -20,14 +20,16 @@
|
||||
#include "Diagnostics.h"
|
||||
#include "Web.h"
|
||||
#include "Server.h"
|
||||
#include "MasterPacketHandler.h"
|
||||
#include "PacketHandler.h"
|
||||
#include "handlers/MasterPacketHandler.h"
|
||||
#include "handlers/DashboardPacketHandler.h"
|
||||
|
||||
#include "routes/ServerState.h"
|
||||
#include "routes/APIRoutes.h"
|
||||
#include "routes/StaticRoutes.h"
|
||||
#include "routes/DashboardRoutes.h"
|
||||
#include "routes/WSRoutes.h"
|
||||
#include "routes/AuthRoutes.h"
|
||||
#include "ServerState.h"
|
||||
#include "APIRoutes.h"
|
||||
#include "StaticRoutes.h"
|
||||
#include "DashboardRoutes.h"
|
||||
#include "WSRoutes.h"
|
||||
#include "AuthRoutes.h"
|
||||
#include "AuthMiddleware.h"
|
||||
|
||||
namespace Game {
|
||||
@@ -97,6 +99,9 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Register dashboard-specific packet handlers
|
||||
DashboardPacketHandler::RegisterDashboardHandlers();
|
||||
|
||||
// Get master info from database
|
||||
std::string masterIP = "localhost";
|
||||
uint32_t masterPort = 1000;
|
||||
@@ -160,10 +165,20 @@ int main(int argc, char** argv) {
|
||||
// Handle master server packets
|
||||
Packet* packet = g_Server->ReceiveFromMaster();
|
||||
if (packet) {
|
||||
MasterPacketHandler::HandleMasterPacket(packet);
|
||||
RakNet::BitStream bitStream(packet->data, packet->length, false);
|
||||
PacketHandler::HandlePacket(bitStream, packet->systemAddress);
|
||||
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
|
||||
Game::web.ReceiveRequests();
|
||||
|
||||
|
||||
28
dDashboardServer/auth/CMakeLists.txt
Normal file
28
dDashboardServer/auth/CMakeLists.txt
Normal 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)
|
||||
68
dDashboardServer/handlers/DashboardPacketHandler.cpp
Normal file
68
dDashboardServer/handlers/DashboardPacketHandler.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
dDashboardServer/handlers/DashboardPacketHandler.h
Normal file
37
dDashboardServer/handlers/DashboardPacketHandler.h
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,30 +5,27 @@
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
#include "RakNetTypes.h"
|
||||
#include "routes/ServerState.h"
|
||||
#include "ServerState.h"
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
namespace MasterPacketHandler {
|
||||
namespace {
|
||||
std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers = {
|
||||
{MessageType::Master::SERVER_INFO, []() {
|
||||
return std::make_unique<ServerInfo>();
|
||||
}},
|
||||
{MessageType::Master::PLAYER_ADDED, []() {
|
||||
return std::make_unique<PlayerAdded>();
|
||||
}},
|
||||
{MessageType::Master::PLAYER_REMOVED, []() {
|
||||
return std::make_unique<PlayerRemoved>();
|
||||
}},
|
||||
{MessageType::Master::SHUTDOWN_RESPONSE, []() {
|
||||
return std::make_unique<ShutdownResponse>();
|
||||
}},
|
||||
{MessageType::Master::SHUTDOWN, []() {
|
||||
return std::make_unique<Shutdown>();
|
||||
}},
|
||||
};
|
||||
}
|
||||
std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers = {
|
||||
{MessageType::Master::SERVER_INFO, []() {
|
||||
return std::make_unique<ServerInfo>();
|
||||
}},
|
||||
{MessageType::Master::PLAYER_ADDED, []() {
|
||||
return std::make_unique<PlayerAdded>();
|
||||
}},
|
||||
{MessageType::Master::PLAYER_REMOVED, []() {
|
||||
return std::make_unique<PlayerRemoved>();
|
||||
}},
|
||||
{MessageType::Master::SHUTDOWN_RESPONSE, []() {
|
||||
return std::make_unique<ShutdownResponse>();
|
||||
}},
|
||||
{MessageType::Master::SHUTDOWN, []() {
|
||||
return std::make_unique<Shutdown>();
|
||||
}},
|
||||
};
|
||||
|
||||
bool ServerInfo::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(bitStream.Read(port));
|
||||
@@ -42,8 +39,6 @@ namespace MasterPacketHandler {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch (serverType) {
|
||||
@@ -94,7 +89,6 @@ namespace MasterPacketHandler {
|
||||
}
|
||||
|
||||
void PlayerAdded::Handle() {
|
||||
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
|
||||
for (auto& world : ServerState::g_WorldInstances) {
|
||||
if (world.mapID == zoneID && world.instanceID == instanceID) {
|
||||
world.players++;
|
||||
@@ -111,7 +105,6 @@ namespace MasterPacketHandler {
|
||||
}
|
||||
|
||||
void PlayerRemoved::Handle() {
|
||||
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
|
||||
for (auto& world : ServerState::g_WorldInstances) {
|
||||
if (world.mapID == zoneID && world.instanceID == instanceID) {
|
||||
if (world.players > 0) world.players--;
|
||||
@@ -129,8 +122,6 @@ namespace MasterPacketHandler {
|
||||
}
|
||||
|
||||
void ShutdownResponse::Handle() {
|
||||
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
|
||||
|
||||
switch (serverType) {
|
||||
case ServiceType::AUTH:
|
||||
ServerState::g_AuthStatus.online = false;
|
||||
@@ -163,47 +154,4 @@ namespace MasterPacketHandler {
|
||||
LOG("Received SHUTDOWN command from Master");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
@@ -74,6 +74,6 @@ namespace MasterPacketHandler {
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
// Main handler function
|
||||
void HandleMasterPacket(Packet* packet);
|
||||
// Master packet handler registry
|
||||
extern std::map<MessageType::Master, std::function<std::unique_ptr<MasterPacket>()>> g_Handlers;
|
||||
}
|
||||
@@ -17,30 +17,7 @@ void RegisterAPIRoutes() {
|
||||
.method = eHTTPMethod::GET,
|
||||
.middleware = { std::make_shared<RequireAuthMiddleware>(0) },
|
||||
.handle = [](HTTPReply& reply, const HTTPContext& context) {
|
||||
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
|
||||
|
||||
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}
|
||||
});
|
||||
}
|
||||
nlohmann::json response = ServerState::GetServerStateJson();
|
||||
|
||||
reply.status = eHTTPStatusCode::OK;
|
||||
reply.message = response.dump();
|
||||
@@ -92,10 +69,18 @@ void RegisterAPIRoutes() {
|
||||
.method = eHTTPMethod::GET,
|
||||
.middleware = { std::make_shared<RequireAuthMiddleware>(0) },
|
||||
.handle = [](HTTPReply& reply, const HTTPContext& context) {
|
||||
nlohmann::json response = {{"count", 0}, {"note", "Not yet implemented"}};
|
||||
reply.status = eHTTPStatusCode::OK;
|
||||
reply.message = response.dump();
|
||||
reply.contentType = eContentType::APPLICATION_JSON;
|
||||
try {
|
||||
const uint32_t count = Database::Get()->GetCharacterCount();
|
||||
nlohmann::json response = {{"count", count}};
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
31
dDashboardServer/routes/CMakeLists.txt
Normal file
31
dDashboardServer/routes/CMakeLists.txt
Normal 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)
|
||||
@@ -25,35 +25,16 @@ void RegisterDashboardRoutes() {
|
||||
env.set_lstrip_blocks(true);
|
||||
|
||||
// Prepare data for template
|
||||
nlohmann::json data;
|
||||
// Get username from auth context
|
||||
data["username"] = context.authenticatedUser;
|
||||
data["gmLevel"] = context.gmLevel;
|
||||
nlohmann::json data = context.GetUserDataJson();
|
||||
|
||||
// Server status (placeholder data - will be updated with real data from master)
|
||||
data["auth"]["online"] = ServerState::g_AuthStatus.online;
|
||||
data["auth"]["players"] = ServerState::g_AuthStatus.players;
|
||||
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}
|
||||
});
|
||||
}
|
||||
// Server status - merge with server state
|
||||
nlohmann::json serverState = ServerState::GetServerStateJson();
|
||||
data.merge_patch(serverState);
|
||||
|
||||
// Statistics
|
||||
const uint32_t accountCount = Database::Get()->GetAccountCount();
|
||||
data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication
|
||||
data["stats"]["totalAccounts"] = accountCount;
|
||||
data["stats"]["totalCharacters"] = 0; // TODO: Add GetCharacterCount to database interface
|
||||
data["stats"]["totalAccounts"] = Database::Get()->GetAccountCount();
|
||||
data["stats"]["totalCharacters"] = Database::Get()->GetCharacterCount();
|
||||
|
||||
// Render template
|
||||
const std::string html = env.render_file("index.jinja2", data);
|
||||
@@ -82,9 +63,8 @@ void RegisterDashboardRoutes() {
|
||||
env.set_trim_blocks(true);
|
||||
env.set_lstrip_blocks(true);
|
||||
|
||||
// Render template with empty username
|
||||
nlohmann::json data;
|
||||
data["username"] = "";
|
||||
// Render template with empty user data (not authenticated)
|
||||
nlohmann::json data = context.GetUserDataJson();
|
||||
const std::string html = env.render_file("login.jinja2", data);
|
||||
|
||||
reply.status = eHTTPStatusCode::OK;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
class HTTPContext;
|
||||
|
||||
void RegisterDashboardRoutes();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include "json.hpp"
|
||||
|
||||
struct ServerStatus {
|
||||
bool online{false};
|
||||
@@ -27,5 +27,26 @@ namespace ServerState {
|
||||
extern ServerStatus g_AuthStatus;
|
||||
extern ServerStatus g_ChatStatus;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,37 +18,14 @@ void RegisterWSRoutes() {
|
||||
}
|
||||
|
||||
void BroadcastDashboardUpdate() {
|
||||
std::lock_guard<std::mutex> lock(ServerState::g_StatusMutex);
|
||||
|
||||
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}
|
||||
});
|
||||
}
|
||||
// Get server state data (auth, chat, worlds) - mutex is acquired internally
|
||||
nlohmann::json data = ServerState::GetServerStateJson();
|
||||
|
||||
// Add statistics
|
||||
try {
|
||||
const uint32_t accountCount = Database::Get()->GetAccountCount();
|
||||
data["stats"]["onlinePlayers"] = 0; // TODO: Get from server communication
|
||||
data["stats"]["totalAccounts"] = accountCount;
|
||||
data["stats"]["totalCharacters"] = 0; // TODO: Add GetCharacterCount to database interface
|
||||
data["stats"]["totalAccounts"] = Database::Get()->GetAccountCount();
|
||||
data["stats"]["totalCharacters"] = Database::Get()->GetCharacterCount();
|
||||
} catch (const std::exception& ex) {
|
||||
LOG_DEBUG("Error getting stats: %s", ex.what());
|
||||
}
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#players">Players</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#servers">Servers</a>
|
||||
</li>
|
||||
<li class="nav-item mt-auto">
|
||||
<a class="nav-link" href="#" id="logoutBtn">Logout</a>
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user