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 supportmaster
parent
ecbc972ea6
commit
7ddf67aa14
|
@ -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
|
|
@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "guiscalingfilter.h"
|
#include "guiscalingfilter.h"
|
||||||
#include "script/scripting_client.h"
|
#include "script/scripting_client.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "chatmessage.h"
|
||||||
|
|
||||||
extern gui::IGUIEnvironment* guienv;
|
extern gui::IGUIEnvironment* guienv;
|
||||||
|
|
||||||
|
@ -1518,12 +1519,34 @@ u16 Client::getHP()
|
||||||
return player->hp;
|
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;
|
return false;
|
||||||
message = m_chat_queue.front();
|
|
||||||
|
ChatMessage *chatMessage = m_chat_queue.front();
|
||||||
m_chat_queue.pop();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1542,14 +1565,13 @@ void Client::typeChatMessage(const std::wstring &message)
|
||||||
sendChatMessage(message);
|
sendChatMessage(message);
|
||||||
|
|
||||||
// Show locally
|
// Show locally
|
||||||
if (message[0] != L'/')
|
if (message[0] != L'/') {
|
||||||
{
|
|
||||||
// compatibility code
|
// compatibility code
|
||||||
if (m_proto_ver < 29) {
|
if (m_proto_ver < 29) {
|
||||||
LocalPlayer *player = m_env.getLocalPlayer();
|
LocalPlayer *player = m_env.getLocalPlayer();
|
||||||
assert(player);
|
assert(player);
|
||||||
std::wstring name = narrow_to_wide(player->getName());
|
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 {
|
} else {
|
||||||
sstr << "Failed to save screenshot '" << filename << "'";
|
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;
|
infostream << sstr.str() << std::endl;
|
||||||
image->drop();
|
image->drop();
|
||||||
}
|
}
|
||||||
|
|
10
src/client.h
10
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
|
#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
|
||||||
|
|
||||||
struct MeshMakeData;
|
struct MeshMakeData;
|
||||||
|
struct ChatMessage;
|
||||||
class MapBlockMesh;
|
class MapBlockMesh;
|
||||||
class IWritableTextureSource;
|
class IWritableTextureSource;
|
||||||
class IWritableShaderSource;
|
class IWritableShaderSource;
|
||||||
|
@ -328,7 +329,8 @@ public:
|
||||||
void handleCommand_BlockData(NetworkPacket* pkt);
|
void handleCommand_BlockData(NetworkPacket* pkt);
|
||||||
void handleCommand_Inventory(NetworkPacket* pkt);
|
void handleCommand_Inventory(NetworkPacket* pkt);
|
||||||
void handleCommand_TimeOfDay(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_ActiveObjectRemoveAdd(NetworkPacket* pkt);
|
||||||
void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
|
void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
|
||||||
void handleCommand_Movement(NetworkPacket* pkt);
|
void handleCommand_Movement(NetworkPacket* pkt);
|
||||||
|
@ -520,9 +522,9 @@ public:
|
||||||
|
|
||||||
void makeScreenshot();
|
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; }
|
ClientScripting *getScript() { return m_script; }
|
||||||
|
@ -629,10 +631,10 @@ private:
|
||||||
// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
|
// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
|
||||||
//s32 m_daynight_i;
|
//s32 m_daynight_i;
|
||||||
//u32 m_daynight_ratio;
|
//u32 m_daynight_ratio;
|
||||||
std::queue<std::wstring> m_chat_queue;
|
|
||||||
std::queue<std::wstring> m_out_chat_queue;
|
std::queue<std::wstring> m_out_chat_queue;
|
||||||
u32 m_last_chat_message_sent;
|
u32 m_last_chat_message_sent;
|
||||||
float m_chat_message_allowance = 5.0f;
|
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)
|
// The authentication methods we can use to enter sudo mode (=change password)
|
||||||
u32 m_sudo_auth_methods;
|
u32 m_sudo_auth_methods;
|
||||||
|
|
|
@ -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)
|
RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
|
||||||
{
|
{
|
||||||
MutexAutoLock clientslock(m_clients_mutex);
|
MutexAutoLock clientslock(m_clients_mutex);
|
||||||
|
|
|
@ -434,6 +434,7 @@ public:
|
||||||
|
|
||||||
/* send to all clients */
|
/* send to all clients */
|
||||||
void sendToAll(NetworkPacket *pkt);
|
void sendToAll(NetworkPacket *pkt);
|
||||||
|
void sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt, u16 min_proto_ver);
|
||||||
|
|
||||||
/* delete a client */
|
/* delete a client */
|
||||||
void DeleteClient(u16 peer_id);
|
void DeleteClient(u16 peer_id);
|
||||||
|
|
|
@ -976,8 +976,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get new messages from client
|
// Get new messages from client
|
||||||
std::wstring message;
|
std::wstring message = L"";
|
||||||
|
|
||||||
while (client.getChatMessage(message)) {
|
while (client.getChatMessage(message)) {
|
||||||
chat_backend.addUnparsedMessage(message);
|
chat_backend.addUnparsedMessage(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,8 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
|
||||||
null_command_handler,
|
null_command_handler,
|
||||||
null_command_handler,
|
null_command_handler,
|
||||||
null_command_handler,
|
null_command_handler,
|
||||||
null_command_handler,
|
{ "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x2F
|
||||||
{ "TOCLIENT_CHAT_MESSAGE", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ChatMessage }, // 0x30
|
{ "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_REMOVE_ADD", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectRemoveAdd }, // 0x31
|
||||||
{ "TOCLIENT_ACTIVE_OBJECT_MESSAGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectMessages }, // 0x32
|
{ "TOCLIENT_ACTIVE_OBJECT_MESSAGES", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ActiveObjectMessages }, // 0x32
|
||||||
{ "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33
|
{ "TOCLIENT_HP", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HP }, // 0x33
|
||||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
#include "util/base64.h"
|
#include "util/base64.h"
|
||||||
|
#include "chatmessage.h"
|
||||||
#include "clientmedia.h"
|
#include "clientmedia.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
@ -142,7 +143,9 @@ void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
|
||||||
}
|
}
|
||||||
void Client::handleCommand_DenySudoMode(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
|
// reset everything and be sad
|
||||||
deleteAuthData();
|
deleteAuthData();
|
||||||
}
|
}
|
||||||
|
@ -395,7 +398,7 @@ void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
|
||||||
<< " dr=" << dr << std::endl;
|
<< " dr=" << dr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
|
void Client::handleCommand_ChatMessageOld(NetworkPacket *pkt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
u16 command
|
u16 command
|
||||||
|
@ -413,8 +416,43 @@ void Client::handleCommand_ChatMessage(NetworkPacket* pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If chat message not consummed by client lua API
|
// 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))) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,12 @@ NetworkPacket& NetworkPacket::operator<<(u64 src)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkPacket& NetworkPacket::operator<<(std::time_t src)
|
||||||
|
{
|
||||||
|
*this << (u64) src;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkPacket& NetworkPacket::operator<<(float src)
|
NetworkPacket& NetworkPacket::operator<<(float src)
|
||||||
{
|
{
|
||||||
checkDataSize(4);
|
checkDataSize(4);
|
||||||
|
@ -360,6 +366,16 @@ NetworkPacket& NetworkPacket::operator>>(u64& dst)
|
||||||
return *this;
|
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)
|
NetworkPacket& NetworkPacket::operator>>(float& dst)
|
||||||
{
|
{
|
||||||
checkReadOffset(m_read_offset, 4);
|
checkReadOffset(m_read_offset, 4);
|
||||||
|
|
|
@ -84,6 +84,9 @@ public:
|
||||||
NetworkPacket& operator>>(u64& dst);
|
NetworkPacket& operator>>(u64& dst);
|
||||||
NetworkPacket& operator<<(u64 src);
|
NetworkPacket& operator<<(u64 src);
|
||||||
|
|
||||||
|
NetworkPacket& operator>>(std::time_t& dst);
|
||||||
|
NetworkPacket& operator<<(std::time_t src);
|
||||||
|
|
||||||
NetworkPacket& operator>>(float& dst);
|
NetworkPacket& operator>>(float& dst);
|
||||||
NetworkPacket& operator<<(float src);
|
NetworkPacket& operator<<(float src);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
instead of guessing based on the active object list.
|
||||||
PROTOCOL VERSION 34:
|
PROTOCOL VERSION 34:
|
||||||
Add sound pitch
|
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
|
// Server's supported network protocol range
|
||||||
#define SERVER_PROTOCOL_VERSION_MIN 24
|
#define SERVER_PROTOCOL_VERSION_MIN 24
|
||||||
|
@ -307,7 +315,17 @@ enum ToClientCommand
|
||||||
|
|
||||||
// (oops, there is some gap here)
|
// (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
|
u16 length
|
||||||
wstring message
|
wstring message
|
||||||
|
|
|
@ -160,8 +160,8 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
|
||||||
null_command_factory,
|
null_command_factory,
|
||||||
null_command_factory,
|
null_command_factory,
|
||||||
null_command_factory,
|
null_command_factory,
|
||||||
null_command_factory,
|
{ "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x2F
|
||||||
{ "TOCLIENT_CHAT_MESSAGE", 0, true }, // 0x30
|
{ "TOCLIENT_CHAT_MESSAGE_OLD", 0, true }, // 0x30
|
||||||
{ "TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD", 0, true }, // 0x31
|
{ "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_ACTIVE_OBJECT_MESSAGES", 0, true }, // 0x32 Special packet, sent by 0 (rel) and 1 (unrel) channel
|
||||||
{ "TOCLIENT_HP", 0, true }, // 0x33
|
{ "TOCLIENT_HP", 0, true }, // 0x33
|
||||||
|
|
|
@ -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.
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <chatmessage.h>
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
@ -644,8 +645,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
|
||||||
|
|
||||||
// Warnings about protocol version can be issued here
|
// Warnings about protocol version can be issued here
|
||||||
if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
|
if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
|
||||||
SendChatMessage(pkt->getPeerId(), L"# Server: WARNING: YOUR CLIENT'S "
|
SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
|
||||||
L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
|
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::string name = player->getName();
|
||||||
std::wstring wname = narrow_to_wide(name);
|
std::wstring wname = narrow_to_wide(name);
|
||||||
|
|
||||||
std::wstring answer_to_sender = handleChat(name, wname, message,
|
std::wstring answer_to_sender = handleChat(name, wname, message, true, player);
|
||||||
true, dynamic_cast<RemotePlayer *>(player));
|
|
||||||
if (!answer_to_sender.empty()) {
|
if (!answer_to_sender.empty()) {
|
||||||
// Send the answer to sender
|
// 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() <<
|
infostream<<"Server: " << player->getName() <<
|
||||||
" supplied invalid password hash" << std::endl;
|
" supplied invalid password hash" << std::endl;
|
||||||
// Wrong old password supplied!!
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,18 +1190,21 @@ void Server::handleCommand_Password(NetworkPacket* pkt)
|
||||||
if (oldpwd != checkpwd) {
|
if (oldpwd != checkpwd) {
|
||||||
infostream << "Server: invalid old password" << std::endl;
|
infostream << "Server: invalid old password" << std::endl;
|
||||||
// Wrong old password supplied!!
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = m_script->setPassword(playername, newpwd);
|
bool success = m_script->setPassword(playername, newpwd);
|
||||||
if (success) {
|
if (success) {
|
||||||
actionstream << player->getName() << " changes password" << std::endl;
|
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 {
|
} else {
|
||||||
actionstream << player->getName() << " tries to change password but "
|
actionstream << player->getName() << " tries to change password but "
|
||||||
<< "it fails" << std::endl;
|
<< "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);
|
bool success = m_script->setPassword(playername, pw_db_field);
|
||||||
if (success) {
|
if (success) {
|
||||||
actionstream << playername << " changes password" << std::endl;
|
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 {
|
} else {
|
||||||
actionstream << playername << " tries to change password but "
|
actionstream << playername << " tries to change password but "
|
||||||
<< "it fails" << std::endl;
|
<< "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."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "l_client.h"
|
#include "l_client.h"
|
||||||
|
#include "chatmessage.h"
|
||||||
#include "clientenvironment.h"
|
#include "clientenvironment.h"
|
||||||
#include "common/c_content.h"
|
#include "common/c_content.h"
|
||||||
#include "common/c_converter.h"
|
#include "common/c_converter.h"
|
||||||
|
@ -80,7 +81,7 @@ int ModApiClient::l_display_chat_message(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::string message = luaL_checkstring(L, 1);
|
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);
|
lua_pushboolean(L, true);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "util/sha1.h"
|
#include "util/sha1.h"
|
||||||
#include "util/hex.h"
|
#include "util/hex.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
#include "chatmessage.h"
|
||||||
|
|
||||||
class ClientNotFoundException : public BaseException
|
class ClientNotFoundException : public BaseException
|
||||||
{
|
{
|
||||||
|
@ -304,7 +305,8 @@ Server::~Server()
|
||||||
infostream<<"Server destructing"<<std::endl;
|
infostream<<"Server destructing"<<std::endl;
|
||||||
|
|
||||||
// Send shutdown message
|
// 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);
|
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
|
// Note things in chat if not in simple singleplayer mode
|
||||||
if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
|
if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
|
||||||
// Send information about server to player in chat
|
// 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);
|
Address addr = getPeerAddress(player->peer_id);
|
||||||
std::string ip_str = addr.serializeString();
|
std::string ip_str = addr.serializeString();
|
||||||
|
@ -1615,21 +1617,29 @@ void Server::SendInventory(PlayerSAO* playerSAO)
|
||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
|
void Server::SendChatMessage(u16 peer_id, const ChatMessage &message)
|
||||||
{
|
{
|
||||||
DSTACK(FUNCTION_NAME);
|
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) {
|
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)
|
if (player->protocol_version < 35)
|
||||||
pkt << unescape_enriched(message);
|
Send(&legacypkt);
|
||||||
else
|
else
|
||||||
pkt << message;
|
Send(&pkt);
|
||||||
|
|
||||||
Send(&pkt);
|
|
||||||
} else {
|
} else {
|
||||||
for (u16 id : m_clients.getClientIDs())
|
m_clients.sendToAllCompat(&pkt, &legacypkt, 35);
|
||||||
SendChatMessage(id, message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2811,8 +2821,10 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send leave chat message to all remaining clients
|
// Send leave chat message to all remaining clients
|
||||||
if(message.length() != 0)
|
if (!message.empty()) {
|
||||||
SendChatMessage(PEER_ID_INEXISTENT,message);
|
SendChatMessage(PEER_ID_INEXISTENT,
|
||||||
|
ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::UpdateCrafting(RemotePlayer *player)
|
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++) {
|
for (u16 i = 0; i < clients.size(); i++) {
|
||||||
u16 cid = clients[i];
|
u16 cid = clients[i];
|
||||||
if (cid != peer_id_to_avoid_sending)
|
if (cid != peer_id_to_avoid_sending)
|
||||||
SendChatMessage(cid, line);
|
SendChatMessage(cid, ChatMessage(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return L"";
|
return L"";
|
||||||
|
@ -3096,7 +3108,7 @@ void Server::notifyPlayer(const char *name, const std::wstring &msg)
|
||||||
if (player->peer_id == PEER_ID_INEXISTENT)
|
if (player->peer_id == PEER_ID_INEXISTENT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SendChatMessage(player->peer_id, msg);
|
SendChatMessage(player->peer_id, ChatMessage(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::showFormspec(const char *playername, const std::string &formspec,
|
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)
|
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,
|
void Server::spawnParticle(const std::string &playername, v3f pos,
|
||||||
|
|
|
@ -38,6 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "clientiface.h"
|
#include "clientiface.h"
|
||||||
#include "remoteplayer.h"
|
#include "remoteplayer.h"
|
||||||
#include "network/networkpacket.h"
|
#include "network/networkpacket.h"
|
||||||
|
#include "chatmessage.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -388,7 +389,7 @@ private:
|
||||||
void SetBlocksNotSent(std::map<v3s16, MapBlock *>& block);
|
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 SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed);
|
||||||
void SendPlayerHP(u16 peer_id);
|
void SendPlayerHP(u16 peer_id);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue