mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-16 18:01:40 +00:00
Implement mod communication channels (#6351)
Implement network communication for channels * Implement ModChannel manager server side to route incoming messages from clients to other clients * Add signal handler switch on client & ModChannelMgr on client to handle channels * Add Lua API bindings + client packet sending + unittests * Implement server message sending * Add callback from received message handler to Lua API using registration method
This commit is contained in:
parent
6df312a608
commit
6f1c907204
37 changed files with 1206 additions and 39 deletions
|
@ -111,8 +111,8 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
|
|||
{ "TOCLIENT_CLOUD_PARAMS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CloudParams }, // 0x54
|
||||
{ "TOCLIENT_FADE_SOUND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FadeSound }, // 0x55
|
||||
{ "TOCLIENT_UPDATE_PLAYER_LIST", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_UpdatePlayerList }, // 0x56
|
||||
null_command_handler,
|
||||
null_command_handler,
|
||||
{ "TOCLIENT_MODCHANNEL_MSG", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ModChannelMsg }, // 0x57
|
||||
{ "TOCLIENT_MODCHANNEL_SIGNAL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ModChannelSignal }, // 0x58
|
||||
null_command_handler,
|
||||
null_command_handler,
|
||||
null_command_handler,
|
||||
|
@ -150,9 +150,9 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
|
|||
null_command_factory, // 0x14
|
||||
null_command_factory, // 0x15
|
||||
null_command_factory, // 0x16
|
||||
null_command_factory, // 0x17
|
||||
null_command_factory, // 0x18
|
||||
null_command_factory, // 0x19
|
||||
{ "TOSERVER_MODCHANNEL_JOIN", 0, true }, // 0x17
|
||||
{ "TOSERVER_MODCHANNEL_LEAVE", 0, true }, // 0x18
|
||||
{ "TOSERVER_MODCHANNEL_MSG", 0, true }, // 0x19
|
||||
null_command_factory, // 0x1a
|
||||
null_command_factory, // 0x1b
|
||||
null_command_factory, // 0x1c
|
||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "map.h"
|
||||
#include "mapsector.h"
|
||||
#include "minimap.h"
|
||||
#include "modchannels.h"
|
||||
#include "nodedef.h"
|
||||
#include "serialization.h"
|
||||
#include "server.h"
|
||||
|
@ -1330,3 +1331,95 @@ void Client::handleCommand_CSMFlavourLimits(NetworkPacket *pkt)
|
|||
{
|
||||
*pkt >> m_csm_flavour_limits >> m_csm_noderange_limit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mod channels
|
||||
*/
|
||||
|
||||
void Client::handleCommand_ModChannelMsg(NetworkPacket *pkt)
|
||||
{
|
||||
std::string channel_name, sender, channel_msg;
|
||||
*pkt >> channel_name >> sender >> channel_msg;
|
||||
|
||||
verbosestream << "Mod channel message received from server " << pkt->getPeerId()
|
||||
<< " on channel " << channel_name << ". sender: `" << sender << "`, message: "
|
||||
<< channel_msg << std::endl;
|
||||
|
||||
if (!m_modchannel_mgr->channelRegistered(channel_name)) {
|
||||
verbosestream << "Server sent us messages on unregistered channel "
|
||||
<< channel_name << ", ignoring." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_script->on_modchannel_message(channel_name, sender, channel_msg);
|
||||
}
|
||||
|
||||
void Client::handleCommand_ModChannelSignal(NetworkPacket *pkt)
|
||||
{
|
||||
u8 signal_tmp;
|
||||
ModChannelSignal signal;
|
||||
std::string channel;
|
||||
|
||||
*pkt >> signal_tmp >> channel;
|
||||
|
||||
signal = (ModChannelSignal)signal_tmp;
|
||||
|
||||
bool valid_signal = true;
|
||||
// @TODO: send Signal to Lua API
|
||||
switch (signal) {
|
||||
case MODCHANNEL_SIGNAL_JOIN_OK:
|
||||
m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
|
||||
infostream << "Server ack our mod channel join on channel `" << channel
|
||||
<< "`, joining." << std::endl;
|
||||
break;
|
||||
case MODCHANNEL_SIGNAL_JOIN_FAILURE:
|
||||
// Unable to join, remove channel
|
||||
m_modchannel_mgr->leaveChannel(channel, 0);
|
||||
infostream << "Server refused our mod channel join on channel `" << channel
|
||||
<< "`" << std::endl;
|
||||
break;
|
||||
case MODCHANNEL_SIGNAL_LEAVE_OK:
|
||||
#ifndef NDEBUG
|
||||
infostream << "Server ack our mod channel leave on channel " << channel
|
||||
<< "`, leaving." << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case MODCHANNEL_SIGNAL_LEAVE_FAILURE:
|
||||
infostream << "Server refused our mod channel leave on channel `" << channel
|
||||
<< "`" << std::endl;
|
||||
break;
|
||||
case MODCHANNEL_SIGNAL_CHANNEL_NOT_REGISTERED:
|
||||
#ifndef NDEBUG
|
||||
// Generally unused, but ensure we don't do an implementation error
|
||||
infostream << "Server tells us we sent a message on channel `" << channel
|
||||
<< "` but we are not registered. Message was dropped." << std::endl;
|
||||
#endif
|
||||
break;
|
||||
case MODCHANNEL_SIGNAL_SET_STATE: {
|
||||
u8 state;
|
||||
*pkt >> state;
|
||||
|
||||
if (state == MODCHANNEL_STATE_INIT || state >= MODCHANNEL_STATE_MAX) {
|
||||
infostream << "Received wrong channel state " << state
|
||||
<< ", ignoring." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
m_modchannel_mgr->setChannelState(channel, (ModChannelState) state);
|
||||
infostream << "Server sets mod channel `" << channel
|
||||
<< "` in read-only mode." << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifndef NDEBUG
|
||||
warningstream << "Received unhandled mod channel signal ID "
|
||||
<< signal << ", ignoring." << std::endl;
|
||||
#endif
|
||||
valid_signal = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If signal is valid, forward it to client side mods
|
||||
if (valid_signal)
|
||||
m_script->on_modchannel_signal(channel, signal);
|
||||
}
|
||||
|
|
|
@ -180,6 +180,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
Backwards compatibility drop
|
||||
Add 'can_zoom' to player object properties
|
||||
Add glow to object properties
|
||||
Mod channels
|
||||
*/
|
||||
|
||||
#define LATEST_PROTOCOL_VERSION 36
|
||||
|
@ -611,6 +612,22 @@ enum ToClientCommand
|
|||
u8[len] player name
|
||||
*/
|
||||
|
||||
TOCLIENT_MODCHANNEL_MSG = 0x57,
|
||||
/*
|
||||
u16 channel name length
|
||||
std::string channel name
|
||||
u16 channel name sender
|
||||
std::string channel name
|
||||
u16 message length
|
||||
std::string message
|
||||
*/
|
||||
TOCLIENT_MODCHANNEL_SIGNAL = 0x58,
|
||||
/*
|
||||
u8 signal id
|
||||
u16 channel name length
|
||||
std::string channel name
|
||||
*/
|
||||
|
||||
TOCLIENT_SRP_BYTES_S_B = 0x60,
|
||||
/*
|
||||
Belonging to AUTH_MECHANISM_SRP.
|
||||
|
@ -645,6 +662,26 @@ enum ToServerCommand
|
|||
[0] u16 TOSERVER_INIT2
|
||||
*/
|
||||
|
||||
TOSERVER_MODCHANNEL_JOIN = 0x17,
|
||||
/*
|
||||
u16 channel name length
|
||||
std::string channel name
|
||||
*/
|
||||
|
||||
TOSERVER_MODCHANNEL_LEAVE = 0x18,
|
||||
/*
|
||||
u16 channel name length
|
||||
std::string channel name
|
||||
*/
|
||||
|
||||
TOSERVER_MODCHANNEL_MSG = 0x19,
|
||||
/*
|
||||
u16 channel name length
|
||||
std::string channel name
|
||||
u16 message length
|
||||
std::string message
|
||||
*/
|
||||
|
||||
TOSERVER_GETBLOCK = 0x20, // Obsolete
|
||||
TOSERVER_ADDNODE = 0x21, // Obsolete
|
||||
TOSERVER_REMOVENODE = 0x22, // Obsolete
|
||||
|
|
|
@ -47,9 +47,9 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
|
|||
null_command_handler, // 0x14
|
||||
null_command_handler, // 0x15
|
||||
null_command_handler, // 0x16
|
||||
null_command_handler, // 0x17
|
||||
null_command_handler, // 0x18
|
||||
null_command_handler, // 0x19
|
||||
{ "TOSERVER_MODCHANNEL_JOIN", TOSERVER_STATE_INGAME, &Server::handleCommand_ModChannelJoin }, // 0x17
|
||||
{ "TOSERVER_MODCHANNEL_LEAVE", TOSERVER_STATE_INGAME, &Server::handleCommand_ModChannelLeave }, // 0x18
|
||||
{ "TOSERVER_MODCHANNEL_MSG", TOSERVER_STATE_INGAME, &Server::handleCommand_ModChannelMsg }, // 0x19
|
||||
null_command_handler, // 0x1a
|
||||
null_command_handler, // 0x1b
|
||||
null_command_handler, // 0x1c
|
||||
|
@ -200,8 +200,8 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
|
|||
{ "TOCLIENT_CLOUD_PARAMS", 0, true }, // 0x54
|
||||
{ "TOCLIENT_FADE_SOUND", 0, true }, // 0x55
|
||||
{ "TOCLIENT_UPDATE_PLAYER_LIST", 0, true }, // 0x56
|
||||
null_command_factory,
|
||||
null_command_factory,
|
||||
{ "TOCLIENT_MODCHANNEL_MSG", 0, true}, // 0x57
|
||||
{ "TOCLIENT_MODCHANNEL_SIGNAL", 0, true}, // 0x58
|
||||
null_command_factory,
|
||||
null_command_factory,
|
||||
null_command_factory,
|
||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_sao.h"
|
||||
#include "emerge.h"
|
||||
#include "mapblock.h"
|
||||
#include "modchannels.h"
|
||||
#include "nodedef.h"
|
||||
#include "remoteplayer.h"
|
||||
#include "rollback_interface.h"
|
||||
|
@ -363,7 +364,7 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
|
|||
actionstream
|
||||
<< "TOSERVER_CLIENT_READY stage 2 client init failed for peer_id: "
|
||||
<< peer_id << std::endl;
|
||||
m_con->DisconnectPeer(peer_id);
|
||||
DisconnectPeer(peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -372,7 +373,7 @@ void Server::handleCommand_ClientReady(NetworkPacket* pkt)
|
|||
errorstream
|
||||
<< "TOSERVER_CLIENT_READY client sent inconsistent data, disconnecting peer_id: "
|
||||
<< peer_id << std::endl;
|
||||
m_con->DisconnectPeer(peer_id);
|
||||
DisconnectPeer(peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -503,7 +504,7 @@ void Server::handleCommand_PlayerPos(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -512,7 +513,7 @@ void Server::handleCommand_PlayerPos(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -564,7 +565,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -573,7 +574,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -745,7 +746,7 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -773,7 +774,7 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -782,7 +783,7 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -839,7 +840,7 @@ void Server::handleCommand_Password(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -892,7 +893,7 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -901,7 +902,7 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -919,7 +920,7 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -972,7 +973,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -981,7 +982,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1411,7 +1412,7 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1420,7 +1421,7 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1462,7 +1463,7 @@ void Server::handleCommand_InventoryFields(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1471,7 +1472,7 @@ void Server::handleCommand_InventoryFields(NetworkPacket* pkt)
|
|||
errorstream << "Server::ProcessData(): Canceling: "
|
||||
"No player object for peer_id=" << pkt->getPeerId()
|
||||
<< " disconnecting peer!" << std::endl;
|
||||
m_con->DisconnectPeer(pkt->getPeerId());
|
||||
DisconnectPeer(pkt->getPeerId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1733,3 +1734,81 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt)
|
|||
|
||||
acceptAuth(pkt->getPeerId(), wantSudo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mod channels
|
||||
*/
|
||||
|
||||
void Server::handleCommand_ModChannelJoin(NetworkPacket *pkt)
|
||||
{
|
||||
std::string channel_name;
|
||||
*pkt >> channel_name;
|
||||
|
||||
NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_SIGNAL, 1 + 2 + channel_name.size(),
|
||||
pkt->getPeerId());
|
||||
|
||||
// Send signal to client to notify join succeed or not
|
||||
if (g_settings->getBool("enable_mod_channels") &&
|
||||
m_modchannel_mgr->joinChannel(channel_name, pkt->getPeerId())) {
|
||||
resp_pkt << (u8) MODCHANNEL_SIGNAL_JOIN_OK;
|
||||
infostream << "Peer " << pkt->getPeerId() << " joined channel " << channel_name
|
||||
<< std::endl;
|
||||
}
|
||||
else {
|
||||
resp_pkt << (u8)MODCHANNEL_SIGNAL_JOIN_FAILURE;
|
||||
infostream << "Peer " << pkt->getPeerId() << " tried to join channel "
|
||||
<< channel_name << ", but was already registered." << std::endl;
|
||||
}
|
||||
resp_pkt << channel_name;
|
||||
Send(&resp_pkt);
|
||||
}
|
||||
|
||||
void Server::handleCommand_ModChannelLeave(NetworkPacket *pkt)
|
||||
{
|
||||
std::string channel_name;
|
||||
*pkt >> channel_name;
|
||||
|
||||
NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_SIGNAL, 1 + 2 + channel_name.size(),
|
||||
pkt->getPeerId());
|
||||
|
||||
// Send signal to client to notify join succeed or not
|
||||
if (g_settings->getBool("enable_mod_channels") &&
|
||||
m_modchannel_mgr->leaveChannel(channel_name, pkt->getPeerId())) {
|
||||
resp_pkt << (u8)MODCHANNEL_SIGNAL_LEAVE_OK;
|
||||
infostream << "Peer " << pkt->getPeerId() << " left channel " << channel_name
|
||||
<< std::endl;
|
||||
} else {
|
||||
resp_pkt << (u8) MODCHANNEL_SIGNAL_LEAVE_FAILURE;
|
||||
infostream << "Peer " << pkt->getPeerId() << " left channel " << channel_name
|
||||
<< ", but was not registered." << std::endl;
|
||||
}
|
||||
resp_pkt << channel_name;
|
||||
Send(&resp_pkt);
|
||||
}
|
||||
|
||||
void Server::handleCommand_ModChannelMsg(NetworkPacket *pkt)
|
||||
{
|
||||
std::string channel_name, channel_msg;
|
||||
*pkt >> channel_name >> channel_msg;
|
||||
|
||||
verbosestream << "Mod channel message received from peer " << pkt->getPeerId()
|
||||
<< " on channel " << channel_name << " message: " << channel_msg << std::endl;
|
||||
|
||||
// If mod channels are not enabled, discard message
|
||||
if (!g_settings->getBool("enable_mod_channels")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If channel not registered, signal it and ignore message
|
||||
if (!m_modchannel_mgr->channelRegistered(channel_name)) {
|
||||
NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_SIGNAL, 1 + 2 + channel_name.size(),
|
||||
pkt->getPeerId());
|
||||
resp_pkt << (u8)MODCHANNEL_SIGNAL_CHANNEL_NOT_REGISTERED << channel_name;
|
||||
Send(&resp_pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
// @TODO: filter, rate limit
|
||||
|
||||
broadcastModChannelMessage(channel_name, channel_msg, pkt->getPeerId());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue