diff options
author | Loïc Blot <nerzhul@users.noreply.github.com> | 2017-07-16 10:47:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-16 10:47:31 +0200 |
commit | 7ddf67aa1478813e12a5fcdfb4986b9e5adfe62f (patch) | |
tree | 0bbbee7ed9470e0de149ec9bdaf6a51693ec0e22 | |
parent | ecbc972ea6a2371d64b1d9c9576d31be36b8ae6a (diff) | |
download | minetest-7ddf67aa1478813e12a5fcdfb4986b9e5adfe62f.tar.gz minetest-7ddf67aa1478813e12a5fcdfb4986b9e5adfe62f.tar.bz2 minetest-7ddf67aa1478813e12a5fcdfb4986b9e5adfe62f.zip |
Chat protocol rewrite (#5117)
* New TOCLIENT_CHAT_MESSAGE packet
* Rename old packet to TOCLIENT_CHAT_MESSAGE_OLD for compat
* Handle TOCLIENT_CHAT_MESSAGE new structure client side
* Client chat queue should use a specific object
* SendChatMessage: use the right packet depending on protocol version (not complete yet)
* Add chatmessage(type) objects and handle them client side (partially)
* Use ChatMessage instead of std::wstring server side
* Update with timestamp support
-rw-r--r-- | src/chatmessage.h | 51 | ||||
-rw-r--r-- | src/client.cpp | 37 | ||||
-rw-r--r-- | src/client.h | 10 | ||||
-rw-r--r-- | src/clientiface.cpp | 26 | ||||
-rw-r--r-- | src/clientiface.h | 1 | ||||
-rw-r--r-- | src/game.cpp | 3 | ||||
-rw-r--r-- | src/network/clientopcodes.cpp | 4 | ||||
-rw-r--r-- | src/network/clientpackethandler.cpp | 44 | ||||
-rw-r--r-- | src/network/networkpacket.cpp | 16 | ||||
-rw-r--r-- | src/network/networkpacket.h | 3 | ||||
-rw-r--r-- | src/network/networkprotocol.h | 22 | ||||
-rw-r--r-- | src/network/serveropcodes.cpp | 4 | ||||
-rw-r--r-- | src/network/serverpackethandler.cpp | 31 | ||||
-rw-r--r-- | src/script/lua_api/l_client.cpp | 3 | ||||
-rw-r--r-- | src/server.cpp | 44 | ||||
-rw-r--r-- | src/server.h | 3 |
16 files changed, 251 insertions, 51 deletions
diff --git a/src/chatmessage.h b/src/chatmessage.h new file mode 100644 index 000000000..3ef855098 --- /dev/null +++ b/src/chatmessage.h @@ -0,0 +1,51 @@ +/* +Minetest +Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef MT_CHATMESSAGE_H +#define MT_CHATMESSAGE_H + +#include <string> +#include <ctime> + +enum ChatMessageType +{ + CHATMESSAGE_TYPE_RAW = 0, + CHATMESSAGE_TYPE_NORMAL = 1, + CHATMESSAGE_TYPE_ANNOUNCE = 2, + CHATMESSAGE_TYPE_SYSTEM = 3, + CHATMESSAGE_TYPE_MAX = 4, +}; + +struct ChatMessage +{ + ChatMessage(const std::wstring &m = L"") : message(m) {} + + ChatMessage(ChatMessageType t, const std::wstring &m, const std::wstring &s = L"", + std::time_t ts = std::time(0)) + : type(t), message(m), sender(s), timestamp(ts) + { + } + + ChatMessageType type = CHATMESSAGE_TYPE_RAW; + std::wstring message = L""; + std::wstring sender = L""; + std::time_t timestamp = std::time(0); +}; + +#endif diff --git a/src/client.cpp b/src/client.cpp index 0f689a714..443059c36 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiscalingfilter.h" #include "script/scripting_client.h" #include "game.h" +#include "chatmessage.h" extern gui::IGUIEnvironment* guienv; @@ -1518,12 +1519,34 @@ u16 Client::getHP() return player->hp; } -bool Client::getChatMessage(std::wstring &message) +bool Client::getChatMessage(std::wstring &res) { - if(m_chat_queue.size() == 0) + if (m_chat_queue.empty()) return false; - message = m_chat_queue.front(); + + ChatMessage *chatMessage = m_chat_queue.front(); m_chat_queue.pop(); + + res = L""; + + switch (chatMessage->type) { + case CHATMESSAGE_TYPE_RAW: + case CHATMESSAGE_TYPE_ANNOUNCE: + case CHATMESSAGE_TYPE_SYSTEM: + res = chatMessage->message; + break; + case CHATMESSAGE_TYPE_NORMAL: { + if (!chatMessage->sender.empty()) + res = L"<" + chatMessage->sender + L"> " + chatMessage->message; + else + res = chatMessage->message; + break; + } + default: + break; + } + + delete chatMessage; return true; } @@ -1542,14 +1565,13 @@ void Client::typeChatMessage(const std::wstring &message) sendChatMessage(message); // Show locally - if (message[0] != L'/') - { + if (message[0] != L'/') { // compatibility code if (m_proto_ver < 29) { LocalPlayer *player = m_env.getLocalPlayer(); assert(player); std::wstring name = narrow_to_wide(player->getName()); - pushToChatQueue((std::wstring)L"<" + name + L"> " + message); + pushToChatQueue(new ChatMessage(CHATMESSAGE_TYPE_NORMAL, message, name)); } } } @@ -1806,7 +1828,8 @@ void Client::makeScreenshot() } else { sstr << "Failed to save screenshot '" << filename << "'"; } - pushToChatQueue(narrow_to_wide(sstr.str())); + pushToChatQueue(new ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + narrow_to_wide(sstr.str()))); infostream << sstr.str() << std::endl; image->drop(); } diff --git a/src/client.h b/src/client.h index 0255b2803..0f0cd8a5e 100644 --- a/src/client.h +++ b/src/client.h @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f struct MeshMakeData; +struct ChatMessage; class MapBlockMesh; class IWritableTextureSource; class IWritableShaderSource; @@ -328,7 +329,8 @@ public: void handleCommand_BlockData(NetworkPacket* pkt); void handleCommand_Inventory(NetworkPacket* pkt); void handleCommand_TimeOfDay(NetworkPacket* pkt); - void handleCommand_ChatMessage(NetworkPacket* pkt); + void handleCommand_ChatMessageOld(NetworkPacket *pkt); + void handleCommand_ChatMessage(NetworkPacket *pkt); void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt); void handleCommand_ActiveObjectMessages(NetworkPacket* pkt); void handleCommand_Movement(NetworkPacket* pkt); @@ -520,9 +522,9 @@ public: void makeScreenshot(); - inline void pushToChatQueue(const std::wstring &input) + inline void pushToChatQueue(ChatMessage *cec) { - m_chat_queue.push(input); + m_chat_queue.push(cec); } ClientScripting *getScript() { return m_script; } @@ -629,10 +631,10 @@ private: // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT //s32 m_daynight_i; //u32 m_daynight_ratio; - std::queue<std::wstring> m_chat_queue; std::queue<std::wstring> m_out_chat_queue; u32 m_last_chat_message_sent; float m_chat_message_allowance = 5.0f; + std::queue<ChatMessage *> m_chat_queue; // The authentication methods we can use to enter sudo mode (=change password) u32 m_sudo_auth_methods; diff --git a/src/clientiface.cpp b/src/clientiface.cpp index a629ccee7..361315c3b 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -693,6 +693,32 @@ void ClientInterface::sendToAll(NetworkPacket *pkt) } } +void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt, + u16 min_proto_ver) +{ + MutexAutoLock clientslock(m_clients_mutex); + for (std::unordered_map<u16, RemoteClient*>::iterator i = m_clients.begin(); + i != m_clients.end(); ++i) { + RemoteClient *client = i->second; + NetworkPacket *pkt_to_send = nullptr; + + if (client->net_proto_version >= min_proto_ver) { + pkt_to_send = pkt; + } else if (client->net_proto_version != 0) { + pkt_to_send = legacypkt; + } else { + warningstream << "Client with unhandled version to handle: '" + << client->net_proto_version << "'"; + continue; + } + + m_con->Send(client->peer_id, + clientCommandFactoryTable[pkt_to_send->getCommand()].channel, + pkt_to_send, + clientCommandFactoryTable[pkt_to_send->getCommand()].reliable); + } +} + RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min) { MutexAutoLock clientslock(m_clients_mutex); diff --git a/src/clientiface.h b/src/clientiface.h index 09855a372..ce74cfece 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -434,6 +434,7 @@ public: /* send to all clients */ void sendToAll(NetworkPacket *pkt); + void sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt, u16 min_proto_ver); /* delete a client */ void DeleteClient(u16 peer_id); diff --git a/src/game.cpp b/src/game.cpp index 88ae9c2b7..639cc29c3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -976,8 +976,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug, } // Get new messages from client - std::wstring message; - + std::wstring message = L""; while (client.getChatMessage(message)) { chat_backend.addUnparsedMessage(message); } diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index cb504b373..f39dd6db6 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -71,8 +71,8 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = null_command_handler, null_command_handler, null_command_handler, - null_command_handler, - { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x30 + { "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x2F + { "TOCLIENT_CHAT_MESSAGE_OLD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessageOld }, // 0x30 { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectRemoveAdd }, // 0x31 { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectMessages }, // 0x32 { "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33 diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index e6f0d7092..bb4db6f47 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client.h" #include "util/base64.h" +#include "chatmessage.h" #include "clientmedia.h" #include "log.h" #include "map.h" @@ -142,7 +143,9 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt) } void Client::handleCommand_DenySudoMode(NetworkPacket* pkt) { - pushToChatQueue(L"Password change denied. Password NOT changed."); + ChatMessage *chatMessage = new ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change denied. Password NOT changed."); + pushToChatQueue(chatMessage); // reset everything and be sad deleteAuthData(); } @@ -395,7 +398,7 @@ void Client::handleCommand_TimeOfDay(NetworkPacket* pkt) << " dr=" << dr << std::endl; } -void Client::handleCommand_ChatMessage(NetworkPacket* pkt) +void Client::handleCommand_ChatMessageOld(NetworkPacket *pkt) { /* u16 command @@ -413,8 +416,43 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt) } // If chat message not consummed by client lua API + // @TODO send this to CSM using ChatMessage object if (!moddingEnabled() || !m_script->on_receiving_message(wide_to_utf8(message))) { - pushToChatQueue(message); + pushToChatQueue(new ChatMessage(message)); + } +} + +void Client::handleCommand_ChatMessage(NetworkPacket *pkt) +{ + /* + u8 version + u8 message_type + u16 sendername length + wstring sendername + u16 length + wstring message + */ + + ChatMessage *chatMessage = new ChatMessage(); + u8 version, message_type; + *pkt >> version >> message_type; + + if (version != 1 || message_type >= CHATMESSAGE_TYPE_MAX) { + delete chatMessage; + return; + } + + *pkt >> chatMessage->sender >> chatMessage->message >> chatMessage->timestamp; + + chatMessage->type = (ChatMessageType) message_type; + + // @TODO send this to CSM using ChatMessage object + if (!moddingEnabled() || !m_script->on_receiving_message( + wide_to_utf8(chatMessage->message))) { + pushToChatQueue(chatMessage); + } else { + // Message was consumed by CSM and should not handled by client, destroying + delete chatMessage; } } diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp index 48cf3a374..78c73d253 100644 --- a/src/network/networkpacket.cpp +++ b/src/network/networkpacket.cpp @@ -275,6 +275,12 @@ NetworkPacket& NetworkPacket::operator<<(u64 src) return *this; } +NetworkPacket& NetworkPacket::operator<<(std::time_t src) +{ + *this << (u64) src; + return *this; +} + NetworkPacket& NetworkPacket::operator<<(float src) { checkDataSize(4); @@ -360,6 +366,16 @@ NetworkPacket& NetworkPacket::operator>>(u64& dst) return *this; } +NetworkPacket& NetworkPacket::operator>>(std::time_t& dst) +{ + checkReadOffset(m_read_offset, 8); + + dst = readU64(&m_data[m_read_offset]); + + m_read_offset += 8; + return *this; +} + NetworkPacket& NetworkPacket::operator>>(float& dst) { checkReadOffset(m_read_offset, 4); diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h index 3058a22ca..7eb8cc3ff 100644 --- a/src/network/networkpacket.h +++ b/src/network/networkpacket.h @@ -84,6 +84,9 @@ public: NetworkPacket& operator>>(u64& dst); NetworkPacket& operator<<(u64 src); + NetworkPacket& operator>>(std::time_t& dst); + NetworkPacket& operator<<(std::time_t src); + NetworkPacket& operator>>(float& dst); NetworkPacket& operator<<(float src); diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 8304d3003..759334839 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -160,9 +160,17 @@ with this program; if not, write to the Free Software Foundation, Inc., instead of guessing based on the active object list. PROTOCOL VERSION 34: Add sound pitch + PROTOCOL VERSION 35: + Rename TOCLIENT_CHAT_MESSAGE to TOCLIENT_CHAT_MESSAGE_OLD (0x30) + Add TOCLIENT_CHAT_MESSAGE (0x2F) + This chat message is a signalisation message containing various informations: + * timestamp + * sender + * type (RAW, NORMAL, ANNOUNCE, SYSTEM) + * content */ -#define LATEST_PROTOCOL_VERSION 34 +#define LATEST_PROTOCOL_VERSION 35 // Server's supported network protocol range #define SERVER_PROTOCOL_VERSION_MIN 24 @@ -307,7 +315,17 @@ enum ToClientCommand // (oops, there is some gap here) - TOCLIENT_CHAT_MESSAGE = 0x30, + TOCLIENT_CHAT_MESSAGE = 0x2F, + /* + u8 version + u8 message_type + u16 sendername length + wstring sendername + u16 length + wstring message + */ + + TOCLIENT_CHAT_MESSAGE_OLD = 0x30, // Deprecated by proto v35 /* u16 length wstring message diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 3f9706d6a..208214369 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -160,8 +160,8 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = null_command_factory, null_command_factory, null_command_factory, - null_command_factory, - { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x30 + { "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F + { "TOCLIENT_CHAT_MESSAGE_OLD", 0, true }, // 0x30 { "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", 0, true }, // 0x31 { "TOCLIENT_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 Special packet, sent by 0 (rel) and 1 (unrel) channel { "TOCLIENT_HP", 0, true }, // 0x33 diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index a2882b2e7..b87daba6b 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <chatmessage.h> #include "server.h" #include "log.h" @@ -644,8 +645,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt) // Warnings about protocol version can be issued here if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) { - SendChatMessage(pkt->getPeerId(), L"# Server: WARNING: YOUR CLIENT'S " - L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!"); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE " + L"WITH THIS SERVER!")); + } } @@ -1077,11 +1080,11 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt) std::string name = player->getName(); std::wstring wname = narrow_to_wide(name); - std::wstring answer_to_sender = handleChat(name, wname, message, - true, dynamic_cast<RemotePlayer *>(player)); + std::wstring answer_to_sender = handleChat(name, wname, message, true, player); if (!answer_to_sender.empty()) { // Send the answer to sender - SendChatMessage(pkt->getPeerId(), answer_to_sender); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_NORMAL, + answer_to_sender, wname)); } } @@ -1171,7 +1174,8 @@ void Server::handleCommand_Password(NetworkPacket* pkt) infostream<<"Server: " << player->getName() << " supplied invalid password hash" << std::endl; // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid new password hash supplied. Password NOT changed."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Invalid new password hash supplied. Password NOT changed.")); return; } @@ -1186,18 +1190,21 @@ void Server::handleCommand_Password(NetworkPacket* pkt) if (oldpwd != checkpwd) { infostream << "Server: invalid old password" << std::endl; // Wrong old password supplied!! - SendChatMessage(pkt->getPeerId(), L"Invalid old password supplied. Password NOT changed."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Invalid old password supplied. Password NOT changed.")); return; } bool success = m_script->setPassword(playername, newpwd); if (success) { actionstream << player->getName() << " changes password" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change successful."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change successful.")); } else { actionstream << player->getName() << " tries to change password but " << "it fails" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change failed or unavailable."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change failed or unavailable.")); } } @@ -1853,11 +1860,13 @@ void Server::handleCommand_FirstSrp(NetworkPacket* pkt) bool success = m_script->setPassword(playername, pw_db_field); if (success) { actionstream << playername << " changes password" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change successful."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change successful.")); } else { actionstream << playername << " tries to change password but " << "it fails" << std::endl; - SendChatMessage(pkt->getPeerId(), L"Password change failed or unavailable."); + SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM, + L"Password change failed or unavailable.")); } } } diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 1077d5f2d..e7d75cce7 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "l_client.h" +#include "chatmessage.h" #include "clientenvironment.h" #include "common/c_content.h" #include "common/c_converter.h" @@ -80,7 +81,7 @@ int ModApiClient::l_display_chat_message(lua_State *L) return 0; std::string message = luaL_checkstring(L, 1); - getClient(L)->pushToChatQueue(utf8_to_wide(message)); + getClient(L)->pushToChatQueue(new ChatMessage(utf8_to_wide(message))); lua_pushboolean(L, true); return 1; } diff --git a/src/server.cpp b/src/server.cpp index 95d2371ff..33384816c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -60,6 +60,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/sha1.h" #include "util/hex.h" #include "database.h" +#include "chatmessage.h" class ClientNotFoundException : public BaseException { @@ -304,7 +305,8 @@ Server::~Server() infostream<<"Server destructing"<<std::endl; // Send shutdown message - SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down"); + SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, + L"*** Server shutting down")); { MutexAutoLock envlock(m_env_mutex); @@ -1107,7 +1109,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) // Note things in chat if not in simple singleplayer mode if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) { // Send information about server to player in chat - SendChatMessage(peer_id, getStatusString()); + SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString())); } Address addr = getPeerAddress(player->peer_id); std::string ip_str = addr.serializeString(); @@ -1615,21 +1617,29 @@ void Server::SendInventory(PlayerSAO* playerSAO) Send(&pkt); } -void Server::SendChatMessage(u16 peer_id, const std::wstring &message) +void Server::SendChatMessage(u16 peer_id, const ChatMessage &message) { DSTACK(FUNCTION_NAME); + + NetworkPacket legacypkt(TOCLIENT_CHAT_MESSAGE_OLD, 0, peer_id); + legacypkt << message.message; + + NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id); + u8 version = 1; + u8 type = message.type; + pkt << version << type << std::wstring(L"") << message.message << message.timestamp; + if (peer_id != PEER_ID_INEXISTENT) { - NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id); + RemotePlayer *player = m_env->getPlayer(peer_id); + if (!player) + return; - if (m_clients.getProtocolVersion(peer_id) < 27) - pkt << unescape_enriched(message); + if (player->protocol_version < 35) + Send(&legacypkt); else - pkt << message; - - Send(&pkt); + Send(&pkt); } else { - for (u16 id : m_clients.getClientIDs()) - SendChatMessage(id, message); + m_clients.sendToAllCompat(&pkt, &legacypkt, 35); } } @@ -2811,8 +2821,10 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason) } // Send leave chat message to all remaining clients - if(message.length() != 0) - SendChatMessage(PEER_ID_INEXISTENT,message); + if (!message.empty()) { + SendChatMessage(PEER_ID_INEXISTENT, + ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message)); + } } void Server::UpdateCrafting(RemotePlayer *player) @@ -2934,7 +2946,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna for (u16 i = 0; i < clients.size(); i++) { u16 cid = clients[i]; if (cid != peer_id_to_avoid_sending) - SendChatMessage(cid, line); + SendChatMessage(cid, ChatMessage(line)); } } return L""; @@ -3096,7 +3108,7 @@ void Server::notifyPlayer(const char *name, const std::wstring &msg) if (player->peer_id == PEER_ID_INEXISTENT) return; - SendChatMessage(player->peer_id, msg); + SendChatMessage(player->peer_id, ChatMessage(msg)); } bool Server::showFormspec(const char *playername, const std::string &formspec, @@ -3271,7 +3283,7 @@ bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override, void Server::notifyPlayers(const std::wstring &msg) { - SendChatMessage(PEER_ID_INEXISTENT,msg); + SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg)); } void Server::spawnParticle(const std::string &playername, v3f pos, diff --git a/src/server.h b/src/server.h index b60482a75..112a94863 100644 --- a/src/server.h +++ b/src/server.h @@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientiface.h" #include "remoteplayer.h" #include "network/networkpacket.h" +#include "chatmessage.h" #include <string> #include <list> #include <map> @@ -388,7 +389,7 @@ private: void SetBlocksNotSent(std::map<v3s16, MapBlock *>& block); - void SendChatMessage(u16 peer_id, const std::wstring &message); + void SendChatMessage(u16 peer_id, const ChatMessage &message); void SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed); void SendPlayerHP(u16 peer_id); |