mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-05 06:50:04 +00:00
d32827b692
Was getting frustrated by the inconsistency in our include statements, which were causing me problems. As a result, I went through and manually re-organized every include statement in non-core files. I'm just gonna copy my rant from Discord: FOR HEADER FILES (.hpp): - everything you use IN THE HEADER must be EXPLICITLY INCLUDED with the exception of things that fall under Core.hpp - you may NOT include ANYTHING ELSE FOR SOURCE FILES (.cpp): - you can #include whatever you want as long as the partner header is included first - anything that gets included by another include is fair game - redundant includes are ok because they'll be harmless AS LONG AS our header files stay lean. the point of this is NOT to optimize the number of includes used all around or make things more efficient necessarily. it's to improve readability & coherence and make it easier to avoid cyclical issues
320 lines
12 KiB
C++
320 lines
12 KiB
C++
#include "Chat.hpp"
|
|
|
|
#include "servers/CNShardServer.hpp"
|
|
|
|
#include "Player.hpp"
|
|
#include "PlayerManager.hpp"
|
|
#include "CustomCommands.hpp"
|
|
|
|
#include <assert.h>
|
|
|
|
std::vector<std::string> Chat::dump;
|
|
|
|
using namespace Chat;
|
|
|
|
static void chatHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto chat = (sP_CL2FE_REQ_SEND_FREECHAT_MESSAGE*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(chat->szFreeChat));
|
|
if (fullChat.length() > 1 && fullChat[0] == CMD_PREFIX) { // PREFIX
|
|
CustomCommands::runCmd(fullChat, sock);
|
|
return;
|
|
}
|
|
|
|
if (plr->iSpecialState & CN_SPECIAL_STATE_FLAG__MUTE_FREECHAT)
|
|
return;
|
|
|
|
std::string logLine = "[FreeChat] " + PlayerManager::getPlayerName(plr, true) + ": " + fullChat;
|
|
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
// send to client
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC, resp);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
resp.iPC_ID = plr->iID;
|
|
resp.iEmoteCode = chat->iEmoteCode;
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC);
|
|
|
|
// send to visible players
|
|
PlayerManager::sendToViewable(sock, resp, P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC);
|
|
}
|
|
|
|
static void menuChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto chat = (sP_CL2FE_REQ_SEND_MENUCHAT_MESSAGE*)data->buf;
|
|
Player *plr = PlayerManager::getPlayer(sock);
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(chat->szFreeChat));
|
|
std::string logLine = "[MenuChat] " + PlayerManager::getPlayerName(plr, true) + ": " + fullChat;
|
|
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
// send to client
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC, resp);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
resp.iPC_ID = PlayerManager::getPlayer(sock)->iID;
|
|
resp.iEmoteCode = chat->iEmoteCode;
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC);
|
|
|
|
// send to visible players
|
|
PlayerManager::sendToViewable(sock, resp, P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC);
|
|
}
|
|
|
|
static void emoteHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto emote = (sP_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
// send to client
|
|
INITSTRUCT(sP_FE2CL_REP_PC_AVATAR_EMOTES_CHAT, resp);
|
|
resp.iEmoteCode = emote->iEmoteCode;
|
|
resp.iID_From = plr->iID;
|
|
sock->sendPacket(resp, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT);
|
|
|
|
// send to visible players (players within render distance)
|
|
PlayerManager::sendToViewable(sock, resp, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT);
|
|
}
|
|
|
|
void Chat::sendServerMessage(CNSocket* sock, std::string msg) {
|
|
INITSTRUCT(sP_FE2CL_PC_MOTD_LOGIN, motd);
|
|
|
|
motd.iType = 1;
|
|
// convert string to u16 and write it to the buffer
|
|
U8toU16(msg, (char16_t*)motd.szSystemMsg, sizeof(motd.szSystemMsg));
|
|
|
|
// send the packet :)
|
|
sock->sendPacket(motd, P_FE2CL_PC_MOTD_LOGIN);
|
|
}
|
|
|
|
static void announcementHandler(CNSocket* sock, CNPacketData* data) {
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
if (plr->accountLevel > 30)
|
|
return; // only players with account level less than 30 (GM) are allowed to use this command
|
|
auto announcement = (sP_CL2FE_GM_REQ_PC_ANNOUNCE*)data->buf;
|
|
|
|
INITSTRUCT(sP_FE2CL_GM_REP_PC_ANNOUNCE, msg);
|
|
msg.iAnnounceType = announcement->iAnnounceType;
|
|
msg.iDuringTime = announcement->iDuringTime;
|
|
memcpy(msg.szAnnounceMsg, announcement->szAnnounceMsg, sizeof(msg.szAnnounceMsg));
|
|
std::map<CNSocket*, Player*>::iterator it;
|
|
|
|
switch (announcement->iAreaType) {
|
|
case 0: // area (all players in viewable chunks)
|
|
sock->sendPacket(msg, P_FE2CL_GM_REP_PC_ANNOUNCE);
|
|
PlayerManager::sendToViewable(sock, msg, P_FE2CL_GM_REP_PC_ANNOUNCE);
|
|
break;
|
|
case 1: // shard
|
|
case 2: // world
|
|
break; // not applicable to OpenFusion
|
|
case 3: // global (all players)
|
|
for (it = PlayerManager::players.begin(); it != PlayerManager::players.end(); it++) {
|
|
CNSocket* allSock = it->first;
|
|
allSock->sendPacket(msg, P_FE2CL_GM_REP_PC_ANNOUNCE);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
std::string logLine = "[Bcast " + std::to_string(announcement->iAreaType) + "] " + PlayerManager::getPlayerName(plr, false) + ": " + AUTOU16TOU8(msg.szAnnounceMsg);
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back("**" + logLine + "**");
|
|
}
|
|
|
|
// Buddy freechatting
|
|
static void buddyChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC, resp);
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);
|
|
|
|
if (otherSock == nullptr)
|
|
return; // buddy offline
|
|
|
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
|
|
|
resp.iFromPCUID = plr->PCStyle.iPC_UID;
|
|
resp.iToPCUID = pkt->iBuddyPCUID;
|
|
resp.iEmoteCode = pkt->iEmoteCode;
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(pkt->szFreeChat));
|
|
|
|
if (fullChat.length() > 1 && fullChat[0] == CMD_PREFIX) { // PREFIX
|
|
CustomCommands::runCmd(fullChat, sock);
|
|
return;
|
|
}
|
|
|
|
if (plr->iSpecialState & CN_SPECIAL_STATE_FLAG__MUTE_FREECHAT)
|
|
return;
|
|
|
|
std::string logLine = "[BuddyChat] " + PlayerManager::getPlayerName(plr) + " (to " + PlayerManager::getPlayerName(otherPlr) + "): " + fullChat;
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC); // confirm send to sender
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC); // broadcast send to receiver
|
|
}
|
|
|
|
// Buddy menuchat
|
|
static void buddyMenuChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC, resp);
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);
|
|
|
|
if (otherSock == nullptr)
|
|
return; // buddy offline
|
|
|
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
|
|
|
resp.iFromPCUID = plr->PCStyle.iPC_UID;
|
|
resp.iToPCUID = pkt->iBuddyPCUID;
|
|
resp.iEmoteCode = pkt->iEmoteCode;
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(pkt->szFreeChat));
|
|
std::string logLine = "[BuddyMenuChat] " + PlayerManager::getPlayerName(plr) + " (to " + PlayerManager::getPlayerName(otherPlr) + "): " + fullChat;
|
|
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC); // confirm send to sender
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC); // broadcast send to receiver
|
|
}
|
|
|
|
static void tradeChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
auto pacdat = (sP_CL2FE_REQ_PC_TRADE_EMOTES_CHAT*)data->buf;
|
|
|
|
CNSocket* otherSock; // weird flip flop because we need to know who the other player is
|
|
if (pacdat->iID_Request == pacdat->iID_From)
|
|
otherSock = PlayerManager::getSockFromID(pacdat->iID_To);
|
|
else
|
|
otherSock = PlayerManager::getSockFromID(pacdat->iID_From);
|
|
|
|
if (otherSock == nullptr)
|
|
return;
|
|
|
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_TRADE_EMOTES_CHAT, resp);
|
|
Player *plr = PlayerManager::getPlayer(sock);
|
|
resp.iID_Request = pacdat->iID_Request;
|
|
resp.iID_From = pacdat->iID_From;
|
|
resp.iID_To = pacdat->iID_To;
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(pacdat->szFreeChat));
|
|
U8toU16(fullChat, resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
|
|
std::string logLine = "[TradeChat] " + PlayerManager::getPlayerName(plr) + " (to " + PlayerManager::getPlayerName(otherPlr) + "): " + fullChat;
|
|
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
resp.iEmoteCode = pacdat->iEmoteCode;
|
|
sock->sendPacket(resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT);
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_PC_TRADE_EMOTES_CHAT);
|
|
}
|
|
|
|
static void groupChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
sP_CL2FE_REQ_SEND_ALL_GROUP_FREECHAT_MESSAGE* chat = (sP_CL2FE_REQ_SEND_ALL_GROUP_FREECHAT_MESSAGE*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(chat->szFreeChat));
|
|
|
|
if (fullChat.length() > 1 && fullChat[0] == CMD_PREFIX) { // PREFIX
|
|
CustomCommands::runCmd(fullChat, sock);
|
|
return;
|
|
}
|
|
|
|
if (plr->iSpecialState & CN_SPECIAL_STATE_FLAG__MUTE_FREECHAT)
|
|
return;
|
|
|
|
std::string logLine = "[GroupChat] " + PlayerManager::getPlayerName(plr, true) + ": " + fullChat;
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
// send to client
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC, resp);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
resp.iSendPCID = plr->iID;
|
|
resp.iEmoteCode = chat->iEmoteCode;
|
|
|
|
if (plr->group == nullptr)
|
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC));
|
|
else
|
|
Groups::sendToGroup(plr->group, (void*)&resp, P_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC));
|
|
}
|
|
|
|
static void groupMenuChatHandler(CNSocket* sock, CNPacketData* data) {
|
|
sP_CL2FE_REQ_SEND_ALL_GROUP_MENUCHAT_MESSAGE* chat = (sP_CL2FE_REQ_SEND_ALL_GROUP_MENUCHAT_MESSAGE*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
std::string fullChat = sanitizeText(AUTOU16TOU8(chat->szFreeChat));
|
|
std::string logLine = "[GroupMenuChat] " + PlayerManager::getPlayerName(plr, true) + ": " + fullChat;
|
|
|
|
std::cout << logLine << std::endl;
|
|
dump.push_back(logLine);
|
|
|
|
// send to client
|
|
INITSTRUCT(sP_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC, resp);
|
|
|
|
U8toU16(fullChat, (char16_t*)&resp.szFreeChat, sizeof(resp.szFreeChat));
|
|
resp.iSendPCID = plr->iID;
|
|
resp.iEmoteCode = chat->iEmoteCode;
|
|
|
|
if (plr->group == nullptr)
|
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC));
|
|
Groups::sendToGroup(plr->group, (void*)&resp, P_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC));
|
|
}
|
|
|
|
// we only allow plain ascii, at least for now
|
|
std::string Chat::sanitizeText(std::string text, bool allowNewlines) {
|
|
int i;
|
|
const int BUFSIZE = 512;
|
|
char buf[BUFSIZE];
|
|
|
|
assert(text.size() < BUFSIZE);
|
|
|
|
i = 0;
|
|
for (char c : text) {
|
|
if (i >= BUFSIZE-1)
|
|
break;
|
|
|
|
if (!allowNewlines && c == '\n')
|
|
continue;
|
|
|
|
if ((c >= ' ' && c <= '~') || c == '\n')
|
|
buf[i++] = c;
|
|
}
|
|
buf[i] = 0;
|
|
|
|
return std::string(buf);
|
|
}
|
|
|
|
void Chat::init() {
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_FREECHAT_MESSAGE, chatHandler);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT, emoteHandler);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_MENUCHAT_MESSAGE, menuChatHandler);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE, buddyChatHandler);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE, buddyMenuChatHandler);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_EMOTES_CHAT, tradeChatHandler);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_ALL_GROUP_FREECHAT_MESSAGE, groupChatHandler);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_ALL_GROUP_MENUCHAT_MESSAGE, groupMenuChatHandler);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_ANNOUNCE, announcementHandler);
|
|
}
|