mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-05-09 16:11:17 +00:00
Final framework, now just cleanup
This commit is contained in:
parent
ddd9ff273e
commit
aedc8a09fe
@ -450,7 +450,6 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
// build chat json data
|
// build chat json data
|
||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
data["action"] = "chat";
|
|
||||||
data["playerName"] = sender.playerName;
|
data["playerName"] = sender.playerName;
|
||||||
data["message"] = message.GetAsString();
|
data["message"] = message.GetAsString();
|
||||||
auto& zoneID = data["zone_id"];
|
auto& zoneID = data["zone_id"];
|
||||||
@ -460,7 +459,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case eChatChannel::LOCAL: {
|
case eChatChannel::LOCAL: {
|
||||||
Game::web.SendWSMessage("WorldChat", data.dump());
|
Game::web.SendWSMessage("chat_local", data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eChatChannel::TEAM: {
|
case eChatChannel::TEAM: {
|
||||||
@ -472,7 +471,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
if (!otherMember) return;
|
if (!otherMember) return;
|
||||||
SendPrivateChatMessage(sender, otherMember, otherMember, message, eChatChannel::TEAM, eChatMessageResponseCode::SENT);
|
SendPrivateChatMessage(sender, otherMember, otherMember, message, eChatChannel::TEAM, eChatMessageResponseCode::SENT);
|
||||||
data["teamID"] = team->teamID;
|
data["teamID"] = team->teamID;
|
||||||
Game::web.SendWSMessage("teamchat", data.dump());
|
Game::web.SendWSMessage("chat_team", data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -528,6 +527,14 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
// only freinds can whispr each other
|
// only freinds can whispr each other
|
||||||
for (const auto& fr : receiver.friends) {
|
for (const auto& fr : receiver.friends) {
|
||||||
if (fr.friendID == sender.playerID) {
|
if (fr.friendID == sender.playerID) {
|
||||||
|
nlohmann::json data;
|
||||||
|
data["sender"] = sender.playerName;
|
||||||
|
data["receiver"] = receiverName;
|
||||||
|
data["message"] = message.GetAsString();
|
||||||
|
data["zone_id"]["map_id"] = sender.zoneID.GetMapID();
|
||||||
|
data["zone_id"]["instance_id"] = sender.zoneID.GetInstanceID();
|
||||||
|
data["zone_id"]["clone_id"] = sender.zoneID.GetCloneID();
|
||||||
|
Game::web.SendWSMessage("chat_private", data);
|
||||||
//To the sender:
|
//To the sender:
|
||||||
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::SENT);
|
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::SENT);
|
||||||
//To the receiver:
|
//To the receiver:
|
||||||
|
@ -69,36 +69,6 @@ void HandleWSChat(mg_connection* connection, json data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleWSSubscribe(mg_connection* connection, json data) {
|
|
||||||
auto check = JSONUtils::CheckRequiredData(data, { "type" });
|
|
||||||
if (!check.empty()) {
|
|
||||||
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
|
||||||
} else {
|
|
||||||
const auto type = data["type"].get<std::string>();
|
|
||||||
LOG_DEBUG("type %s subscribed", type.c_str());
|
|
||||||
const auto sub = magic_enum::enum_cast<eWSSubscription>(type).value_or(eWSSubscription::INVALID);
|
|
||||||
if (sub != eWSSubscription::INVALID) {
|
|
||||||
connection->data[GeneralUtils::ToUnderlying(sub)] = 1;
|
|
||||||
mg_ws_send(connection, "{\"status\":\"subscribed\"}", 18, WEBSOCKET_OP_TEXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleWSUnsubscribe(mg_connection* connection, json data) {
|
|
||||||
auto check = JSONUtils::CheckRequiredData(data, { "type" });
|
|
||||||
if (!check.empty()) {
|
|
||||||
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
|
||||||
} else {
|
|
||||||
const auto type = data["type"].get<std::string>();
|
|
||||||
LOG_DEBUG("type %s unsubscribed", type.c_str());
|
|
||||||
const auto sub = magic_enum::enum_cast<eWSSubscription>(type).value_or(eWSSubscription::INVALID);
|
|
||||||
if (sub != eWSSubscription::INVALID) {
|
|
||||||
connection->data[GeneralUtils::ToUnderlying(sub)] = 0;
|
|
||||||
mg_ws_send(connection, "{\"status\":\"unsubscribed\"}", 18, WEBSOCKET_OP_TEXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatWeb::RegisterRoutes() {
|
void ChatWeb::RegisterRoutes() {
|
||||||
// REST API v1 routes
|
// REST API v1 routes
|
||||||
std::string v1_route = "/api/v1/";
|
std::string v1_route = "/api/v1/";
|
||||||
@ -120,19 +90,16 @@ void ChatWeb::RegisterRoutes() {
|
|||||||
.handle = HandleHTTPAnnounceRequest
|
.handle = HandleHTTPAnnounceRequest
|
||||||
});
|
});
|
||||||
|
|
||||||
// WebSocket Actions
|
// WebSocket Events
|
||||||
Game::web.RegisterWSAction({
|
Game::web.RegisterWSEvent({
|
||||||
.action = "subscribe",
|
.name = "chat",
|
||||||
.handle = HandleWSSubscribe
|
|
||||||
});
|
|
||||||
|
|
||||||
Game::web.RegisterWSAction({
|
|
||||||
.action = "unsubscribe",
|
|
||||||
.handle = HandleWSUnsubscribe
|
|
||||||
});
|
|
||||||
|
|
||||||
Game::web.RegisterWSAction({
|
|
||||||
.action = "chat",
|
|
||||||
.handle = HandleWSChat
|
.handle = HandleWSChat
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// WebSocket subscriptions
|
||||||
|
Game::web.RegisterWSSubscription("chat_local");
|
||||||
|
Game::web.RegisterWSSubscription("chat_team");
|
||||||
|
Game::web.RegisterWSSubscription("chat_private");
|
||||||
|
Game::web.RegisterWSSubscription("player");
|
||||||
|
Game::web.RegisterWSSubscription("team");
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,6 @@
|
|||||||
|
|
||||||
#include "Web.h"
|
#include "Web.h"
|
||||||
|
|
||||||
enum class eWSSubscription {
|
|
||||||
WORLD_CHAT,
|
|
||||||
PRIVATE_CHAT,
|
|
||||||
TEAM_CHAT,
|
|
||||||
TEAM,
|
|
||||||
PLAYER,
|
|
||||||
INVALID
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ChatWeb {
|
namespace ChatWeb {
|
||||||
void RegisterRoutes();
|
void RegisterRoutes();
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
zoneID["map_id"] = data.zoneID.GetMapID();
|
zoneID["map_id"] = data.zoneID.GetMapID();
|
||||||
zoneID["instance_id"] = data.zoneID.GetInstanceID();
|
zoneID["instance_id"] = data.zoneID.GetInstanceID();
|
||||||
zoneID["clone_id"] = data.zoneID.GetCloneID();
|
zoneID["clone_id"] = data.zoneID.GetCloneID();
|
||||||
Game::web.SendWSMessage("player", wsdata.dump());
|
Game::web.SendWSMessage("player", wsdata);
|
||||||
Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID());
|
Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID());
|
||||||
m_PlayersToRemove.erase(playerId);
|
m_PlayersToRemove.erase(playerId);
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ void PlayerContainer::RemovePlayer(const LWOOBJID playerID) {
|
|||||||
wsdata["type"] = "remove";
|
wsdata["type"] = "remove";
|
||||||
wsdata["playerName"] = player.playerName;
|
wsdata["playerName"] = player.playerName;
|
||||||
wsdata["playerID"] = player.playerID;
|
wsdata["playerID"] = player.playerID;
|
||||||
Game::web.SendWSMessage("player", wsdata.dump());
|
Game::web.SendWSMessage("player", wsdata);
|
||||||
|
|
||||||
m_PlayerCount--;
|
m_PlayerCount--;
|
||||||
LOG("Removed user: %llu", playerID);
|
LOG("Removed user: %llu", playerID);
|
||||||
|
123
dWeb/Web.cpp
123
dWeb/Web.cpp
@ -14,7 +14,8 @@ namespace Game {
|
|||||||
namespace {
|
namespace {
|
||||||
const char * json_content_type = "application/json";
|
const char * json_content_type = "application/json";
|
||||||
std::map<std::pair<eHTTPMethod, std::string>, HTTPRoute> g_HTTPRoutes;
|
std::map<std::pair<eHTTPMethod, std::string>, HTTPRoute> g_HTTPRoutes;
|
||||||
std::map<std::string, WSAction> g_WSactions;
|
std::map<std::string, WSEvent> g_WSEvents;
|
||||||
|
std::vector<std::string> g_WSSubscriptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
@ -80,17 +81,17 @@ void HandleWSMessage(mg_connection* connection, const mg_ws_message* ws_msg) {
|
|||||||
auto data = GeneralUtils::TryParse<json>(std::string(ws_msg->data.buf, ws_msg->data.len));
|
auto data = GeneralUtils::TryParse<json>(std::string(ws_msg->data.buf, ws_msg->data.len));
|
||||||
if (data) {
|
if (data) {
|
||||||
const auto& good_data = data.value();
|
const auto& good_data = data.value();
|
||||||
auto check = JSONUtils::CheckRequiredData(good_data, { "action" });
|
auto check = JSONUtils::CheckRequiredData(good_data, { "event" });
|
||||||
if (!check.empty()) {
|
if (!check.empty()) {
|
||||||
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
||||||
} else {
|
} else {
|
||||||
const auto action = good_data["action"].get<std::string>();
|
const auto event = good_data["event"].get<std::string>();
|
||||||
const auto actionItr = g_WSactions.find(action);
|
const auto eventItr = g_WSEvents.find(event);
|
||||||
if (actionItr != g_WSactions.end()) {
|
if (eventItr != g_WSEvents.end()) {
|
||||||
const auto& [_, action] = *actionItr;
|
const auto& [_, event] = *eventItr;
|
||||||
action.handle(connection, good_data);
|
event.handle(connection, good_data);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Received invalid websocket action: %s", action.c_str());
|
LOG_DEBUG("Received invalid websocket event: %s", event.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -99,6 +100,61 @@ void HandleWSMessage(mg_connection* connection, const mg_ws_message* ws_msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandleWSSubscribe(mg_connection* connection, json data) {
|
||||||
|
auto check = JSONUtils::CheckRequiredData(data, { "subscription" });
|
||||||
|
if (!check.empty()) {
|
||||||
|
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
||||||
|
} else {
|
||||||
|
const auto subscription = data["subscription"].get<std::string>();
|
||||||
|
LOG_DEBUG("subscription %s subscribed", subscription.c_str());
|
||||||
|
// check subscription vector
|
||||||
|
auto subItr = std::find(g_WSSubscriptions.begin(), g_WSSubscriptions.end(), subscription);
|
||||||
|
if (subItr != g_WSSubscriptions.end()) {
|
||||||
|
// get index of subscription
|
||||||
|
auto index = std::distance(g_WSSubscriptions.begin(), subItr);
|
||||||
|
connection->data[index] = 1;
|
||||||
|
mg_ws_send(connection, "{\"status\":\"subscribed\"}", 23, WEBSOCKET_OP_TEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleWSUnsubscribe(mg_connection* connection, json data) {
|
||||||
|
auto check = JSONUtils::CheckRequiredData(data, { "subscription" });
|
||||||
|
if (!check.empty()) {
|
||||||
|
LOG_DEBUG("Received invalid websocket message: %s", check.c_str());
|
||||||
|
} else {
|
||||||
|
const auto subscription = data["subscription"].get<std::string>();
|
||||||
|
LOG_DEBUG("subscription %s unsubscribed", subscription.c_str());
|
||||||
|
// check subscription vector
|
||||||
|
auto subItr = std::find(g_WSSubscriptions.begin(), g_WSSubscriptions.end(), subscription);
|
||||||
|
if (subItr != g_WSSubscriptions.end()) {
|
||||||
|
// get index of subscription
|
||||||
|
auto index = std::distance(g_WSSubscriptions.begin(), subItr);
|
||||||
|
connection->data[index] = 0;
|
||||||
|
mg_ws_send(connection, "{\"status\":\"unsubscribed\"}", 25, WEBSOCKET_OP_TEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleWSGetSubscriptions(mg_connection* connection, json data) {
|
||||||
|
// list subscribed and non subscribed subscriptions
|
||||||
|
json response;
|
||||||
|
// check subscription vector
|
||||||
|
for (const auto& sub : g_WSSubscriptions) {
|
||||||
|
auto subItr = std::find(g_WSSubscriptions.begin(), g_WSSubscriptions.end(), sub);
|
||||||
|
if (subItr != g_WSSubscriptions.end()) {
|
||||||
|
// get index of subscription
|
||||||
|
auto index = std::distance(g_WSSubscriptions.begin(), subItr);
|
||||||
|
if (connection->data[index] == 1) {
|
||||||
|
response["subscribed"].push_back(sub);
|
||||||
|
} else {
|
||||||
|
response["unsubscribed"].push_back(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mg_ws_send(connection, response.dump().c_str(), response.dump().size(), WEBSOCKET_OP_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
void HandleMessages(mg_connection* connection, int message, void* message_data) {
|
void HandleMessages(mg_connection* connection, int message, void* message_data) {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case MG_EV_HTTP_MSG:
|
case MG_EV_HTTP_MSG:
|
||||||
@ -121,12 +177,23 @@ void Web::RegisterHTTPRoute(HTTPRoute route) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web::RegisterWSAction(WSAction action) {
|
void Web::RegisterWSEvent(WSEvent event) {
|
||||||
auto [_, success] = g_WSactions.try_emplace(action.action, action);
|
auto [_, success] = g_WSEvents.try_emplace(event.name, event);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
LOG_DEBUG("Failed to register WS action %s", action.action.c_str());
|
LOG_DEBUG("Failed to register WS event %s", event.name.c_str());
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Registered WS action %s", action.action.c_str());
|
LOG_DEBUG("Registered WS event %s", event.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Web::RegisterWSSubscription(const std::string& subscription) {
|
||||||
|
// check that subsction is not already in the vector
|
||||||
|
auto subItr = std::find(g_WSSubscriptions.begin(), g_WSSubscriptions.end(), subscription);
|
||||||
|
if (subItr != g_WSSubscriptions.end()) {
|
||||||
|
LOG_DEBUG("Failed to register WS subscription %s: duplicate", subscription.c_str());
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("Registered WS subscription %s", subscription.c_str());
|
||||||
|
g_WSSubscriptions.push_back(subscription);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +216,23 @@ bool Web::Startup(const std::string& listen_ip, const uint32_t listen_port) {
|
|||||||
LOG("Failed to create web server listener on %s", listen_address.c_str());
|
LOG("Failed to create web server listener on %s", listen_address.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebSocket Events
|
||||||
|
Game::web.RegisterWSEvent({
|
||||||
|
.name = "subscribe",
|
||||||
|
.handle = HandleWSSubscribe
|
||||||
|
});
|
||||||
|
|
||||||
|
Game::web.RegisterWSEvent({
|
||||||
|
.name = "unsubscribe",
|
||||||
|
.handle = HandleWSUnsubscribe
|
||||||
|
});
|
||||||
|
|
||||||
|
Game::web.RegisterWSEvent({
|
||||||
|
.name = "getSubscriptions",
|
||||||
|
.handle = HandleWSGetSubscriptions
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,10 +240,19 @@ void Web::ReceiveRequests() {
|
|||||||
mg_mgr_poll(&mgr, 15);
|
mg_mgr_poll(&mgr, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web::SendWSMessage(const std::string subscription, const std::string& message) {
|
void Web::SendWSMessage(const std::string subscription, json& data) {
|
||||||
|
// find subscription
|
||||||
|
auto subItr = std::find(g_WSSubscriptions.begin(), g_WSSubscriptions.end(), subscription);
|
||||||
|
if (subItr == g_WSSubscriptions.end()) {
|
||||||
|
LOG_DEBUG("Failed to send WS message: subscription %s not found", subscription.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// tell it the event type
|
||||||
|
data["event"] = subscription;
|
||||||
|
auto index = std::distance(g_WSSubscriptions.begin(), subItr);
|
||||||
for (struct mg_connection *wc = Game::web.mgr.conns; wc != NULL; wc = wc->next) {
|
for (struct mg_connection *wc = Game::web.mgr.conns; wc != NULL; wc = wc->next) {
|
||||||
if (wc->is_websocket /* && wc->data[GeneralUtils::ToUnderlying(sub)] == 1*/) {
|
if (wc->is_websocket && wc->data[index] == 1) {
|
||||||
mg_ws_send(wc, message.c_str(), message.size(), WEBSOCKET_OP_TEXT);
|
mg_ws_send(wc, data.dump().c_str(), data.dump().size(), WEBSOCKET_OP_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,8 +28,8 @@ struct HTTPRoute {
|
|||||||
std::function<void(HTTPReply&, const std::string&)> handle;
|
std::function<void(HTTPReply&, const std::string&)> handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WSAction {
|
struct WSEvent {
|
||||||
std::string action;
|
std::string name;
|
||||||
std::function<void(mg_connection*, nlohmann::json)> handle;
|
std::function<void(mg_connection*, nlohmann::json)> handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,10 +44,11 @@ public:
|
|||||||
Web();
|
Web();
|
||||||
~Web();
|
~Web();
|
||||||
void ReceiveRequests();
|
void ReceiveRequests();
|
||||||
void static SendWSMessage(std::string sub, const std::string& message);
|
void static SendWSMessage(std::string sub, nlohmann::json& message);
|
||||||
bool Startup(const std::string& listen_ip, const uint32_t listen_port);
|
bool Startup(const std::string& listen_ip, const uint32_t listen_port);
|
||||||
void RegisterHTTPRoute(HTTPRoute route);
|
void RegisterHTTPRoute(HTTPRoute route);
|
||||||
void RegisterWSAction(WSAction action);
|
void RegisterWSEvent(WSEvent event);
|
||||||
|
void RegisterWSSubscription(const std::string& subscription);
|
||||||
private:
|
private:
|
||||||
mg_mgr mgr;
|
mg_mgr mgr;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user