summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordP <dp@dpointer.org>2021-09-20 00:09:06 +0300
committerGitHub <noreply@github.com>2021-09-19 23:09:06 +0200
commit31cf9e888b1129ed8147a0ce1ee0bdbf7c121c9b (patch)
tree05a706ddc8b269445c4ea3b28959690b7774ae32
parentd9f8ed7bdf5de55b339636f96d8958d04e6d6c6c (diff)
downloadopenttd-31cf9e888b1129ed8147a0ce1ee0bdbf7c121c9b.tar.xz
Add: [Network] external chat messages for remote admins (#9563)
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/network/core/tcp_admin.cpp2
-rw-r--r--src/network/core/tcp_admin.h12
-rw-r--r--src/network/core/tcp_game.cpp2
-rw-r--r--src/network/core/tcp_game.h11
-rw-r--r--src/network/network.cpp6
-rw-r--r--src/network/network_admin.cpp19
-rw-r--r--src/network/network_admin.h1
-rw-r--r--src/network/network_chat_gui.cpp2
-rw-r--r--src/network/network_client.cpp16
-rw-r--r--src/network/network_client.h1
-rw-r--r--src/network/network_func.h1
-rw-r--r--src/network/network_internal.h2
-rw-r--r--src/network/network_server.cpp39
-rw-r--r--src/network/network_server.h1
-rw-r--r--src/network/network_type.h1
16 files changed, 112 insertions, 5 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 0dc42071e..ea8908a5e 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -2412,6 +2412,7 @@ STR_NETWORK_CHAT_TO_COMPANY :[Team] To {RAW_
STR_NETWORK_CHAT_CLIENT :[Private] {RAW_STRING}: {WHITE}{RAW_STRING}
STR_NETWORK_CHAT_TO_CLIENT :[Private] To {RAW_STRING}: {WHITE}{RAW_STRING}
STR_NETWORK_CHAT_ALL :[All] {RAW_STRING}: {WHITE}{RAW_STRING}
+STR_NETWORK_CHAT_EXTERNAL :[{3:RAW_STRING}] {0:RAW_STRING}: {WHITE}{1:RAW_STRING}
STR_NETWORK_CHAT_OSKTITLE :{BLACK}Enter text for network chat
# Network messages
diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp
index e1b18549c..de1c22131 100644
--- a/src/network/core/tcp_admin.cpp
+++ b/src/network/core/tcp_admin.cpp
@@ -53,6 +53,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
case ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY: return this->Receive_ADMIN_UPDATE_FREQUENCY(p);
case ADMIN_PACKET_ADMIN_POLL: return this->Receive_ADMIN_POLL(p);
case ADMIN_PACKET_ADMIN_CHAT: return this->Receive_ADMIN_CHAT(p);
+ case ADMIN_PACKET_ADMIN_EXTERNAL_CHAT: return this->Receive_ADMIN_EXTERNAL_CHAT(p);
case ADMIN_PACKET_ADMIN_RCON: return this->Receive_ADMIN_RCON(p);
case ADMIN_PACKET_ADMIN_GAMESCRIPT: return this->Receive_ADMIN_GAMESCRIPT(p);
case ADMIN_PACKET_ADMIN_PING: return this->Receive_ADMIN_PING(p);
@@ -132,6 +133,7 @@ NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p) { ret
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_POLL); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_CHAT); }
+NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_EXTERNAL_CHAT); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_RCON); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_GAMESCRIPT); }
NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_PING); }
diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h
index 6d498ce5d..33ab7b049 100644
--- a/src/network/core/tcp_admin.h
+++ b/src/network/core/tcp_admin.h
@@ -30,6 +30,7 @@ enum PacketAdminType {
ADMIN_PACKET_ADMIN_RCON, ///< The admin sends a remote console command.
ADMIN_PACKET_ADMIN_GAMESCRIPT, ///< The admin sends a JSON string for the GameScript.
ADMIN_PACKET_ADMIN_PING, ///< The admin sends a ping to the server, expecting a ping-reply (PONG) packet.
+ ADMIN_PACKET_ADMIN_EXTERNAL_CHAT, ///< The admin sends a chat message from external source.
ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin.
ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned.
@@ -164,6 +165,17 @@ protected:
virtual NetworkRecvStatus Receive_ADMIN_CHAT(Packet *p);
/**
+ * Send chat from the external source:
+ * string Name of the source this message came from.
+ * uint16 TextColour to use for the message.
+ * string Name of the user who sent the messsage.
+ * string Message.
+ * @param p The packet that was just received.
+ * @return The state the network should have.
+ */
+ virtual NetworkRecvStatus Receive_ADMIN_EXTERNAL_CHAT(Packet *p);
+
+ /**
* Execute a command on the servers console:
* string Command to be executed.
* @param p The packet that was just received.
diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp
index 9ac53c597..2e9965913 100644
--- a/src/network/core/tcp_game.cpp
+++ b/src/network/core/tcp_game.cpp
@@ -94,6 +94,7 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p)
case PACKET_SERVER_COMMAND: return this->Receive_SERVER_COMMAND(p);
case PACKET_CLIENT_CHAT: return this->Receive_CLIENT_CHAT(p);
case PACKET_SERVER_CHAT: return this->Receive_SERVER_CHAT(p);
+ case PACKET_SERVER_EXTERNAL_CHAT: return this->Receive_SERVER_EXTERNAL_CHAT(p);
case PACKET_CLIENT_SET_PASSWORD: return this->Receive_CLIENT_SET_PASSWORD(p);
case PACKET_CLIENT_SET_NAME: return this->Receive_CLIENT_SET_NAME(p);
case PACKET_CLIENT_QUIT: return this->Receive_CLIENT_QUIT(p);
@@ -180,6 +181,7 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMMAND(Packet *p) {
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMMAND(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMMAND); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_CHAT); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CHAT); }
+NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_EXTERNAL_CHAT); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_SET_PASSWORD(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_PASSWORD); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_SET_NAME(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_SET_NAME); }
NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_QUIT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_QUIT); }
diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h
index 833b9077f..591a91ac1 100644
--- a/src/network/core/tcp_game.h
+++ b/src/network/core/tcp_game.h
@@ -99,6 +99,7 @@ enum PacketGameType {
/* Human communication! */
PACKET_CLIENT_CHAT, ///< Client said something that should be distributed.
PACKET_SERVER_CHAT, ///< Server distributing the message of a client (or itself).
+ PACKET_SERVER_EXTERNAL_CHAT, ///< Server distributing the message from external source.
/* Remote console. */
PACKET_CLIENT_RCON, ///< Client asks the server to execute some command.
@@ -379,6 +380,16 @@ protected:
virtual NetworkRecvStatus Receive_SERVER_CHAT(Packet *p);
/**
+ * Sends a chat-packet for external source to the client:
+ * string Name of the source this message came from.
+ * uint16 TextColour to use for the message.
+ * string Name of the user who sent the messsage.
+ * string Message (max NETWORK_CHAT_LENGTH).
+ * @param p The packet that was just received.
+ */
+ virtual NetworkRecvStatus Receive_SERVER_EXTERNAL_CHAT(Packet *p);
+
+ /**
* Set the password for the clients current company:
* string The password.
* @param p The packet that was just received.
diff --git a/src/network/network.cpp b/src/network/network.cpp
index dd4933356..09b748fc5 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -217,7 +217,7 @@ bool NetworkCompanyIsPassworded(CompanyID company_id)
/* This puts a text-message to the console, or in the future, the chat-box,
* (to keep it all a bit more general)
* If 'self_send' is true, this is the client who is sending the message */
-void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, int64 data)
+void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str, int64 data, const std::string &data_str)
{
StringID strid;
switch (action) {
@@ -248,6 +248,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send,
case NETWORK_ACTION_CHAT_COMPANY: strid = self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY; break;
case NETWORK_ACTION_CHAT_CLIENT: strid = self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT; break;
case NETWORK_ACTION_KICKED: strid = STR_NETWORK_MESSAGE_KICKED; break;
+ case NETWORK_ACTION_EXTERNAL_CHAT: strid = STR_NETWORK_CHAT_EXTERNAL; break;
default: strid = STR_NETWORK_CHAT_ALL; break;
}
@@ -255,6 +256,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send,
SetDParamStr(0, name);
SetDParamStr(1, str);
SetDParam(2, data);
+ SetDParamStr(3, data_str);
/* All of these strings start with "***". These characters are interpreted as both left-to-right and
* right-to-left characters depending on the context. As the next text might be an user's name, the
@@ -265,7 +267,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send,
Debug(desync, 1, "msg: {:08x}; {:02x}; {}", _date, _date_fract, message);
IConsolePrint(colour, message);
- NetworkAddChatMessage((TextColour)colour, _settings_client.gui.network_chat_timeout, message);
+ NetworkAddChatMessage(colour, _settings_client.gui.network_chat_timeout, message);
}
/* Calculate the frame-lag of a client */
diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp
index 811daaced..49b222f36 100644
--- a/src/network/network_admin.cpp
+++ b/src/network/network_admin.cpp
@@ -790,6 +790,25 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p)
return NETWORK_RECV_STATUS_OKAY;
}
+NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet *p)
+{
+ if (this->status == ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED);
+
+ std::string source = p->Recv_string(NETWORK_CHAT_LENGTH);
+ TextColour colour = (TextColour)p->Recv_uint16();
+ std::string user = p->Recv_string(NETWORK_CHAT_LENGTH);
+ std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH);
+
+ if (!IsValidConsoleColour(colour)) {
+ Debug(net, 1, "[admin] Not supported chat colour {} ({}, {}, {}) from '{}' ({}).", (uint16)colour, source, user, msg, this->admin_name, this->admin_version);
+ return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET);
+ }
+
+ NetworkServerSendExternalChat(source, colour, user, msg);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
/*
* Useful wrapper functions
*/
diff --git a/src/network/network_admin.h b/src/network/network_admin.h
index 9d7f0eef4..6739f8337 100644
--- a/src/network/network_admin.h
+++ b/src/network/network_admin.h
@@ -29,6 +29,7 @@ protected:
NetworkRecvStatus Receive_ADMIN_UPDATE_FREQUENCY(Packet *p) override;
NetworkRecvStatus Receive_ADMIN_POLL(Packet *p) override;
NetworkRecvStatus Receive_ADMIN_CHAT(Packet *p) override;
+ NetworkRecvStatus Receive_ADMIN_EXTERNAL_CHAT(Packet *p) override;
NetworkRecvStatus Receive_ADMIN_RCON(Packet *p) override;
NetworkRecvStatus Receive_ADMIN_GAMESCRIPT(Packet *p) override;
NetworkRecvStatus Receive_ADMIN_PING(Packet *p) override;
diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp
index b42f0c562..8645c11da 100644
--- a/src/network/network_chat_gui.cpp
+++ b/src/network/network_chat_gui.cpp
@@ -95,7 +95,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const std::st
ChatMessage *cmsg = &_chatmsg_list.emplace_front();
cmsg->message = message;
- cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE;
+ cmsg->colour = colour;
cmsg->remove_time = std::chrono::steady_clock::now() + std::chrono::seconds(duration);
_chatmessage_dirty_time = std::chrono::steady_clock::now();
diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp
index 774c6f776..22f7278f3 100644
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -963,6 +963,22 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CHAT(Packet *p)
return NETWORK_RECV_STATUS_OKAY;
}
+NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_EXTERNAL_CHAT(Packet *p)
+{
+ if (this->status != STATUS_ACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+
+ std::string source = p->Recv_string(NETWORK_CHAT_LENGTH);
+ TextColour colour = (TextColour)p->Recv_uint16();
+ std::string user = p->Recv_string(NETWORK_CHAT_LENGTH);
+ std::string msg = p->Recv_string(NETWORK_CHAT_LENGTH);
+
+ if (!IsValidConsoleColour(colour)) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+
+ NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, 0, source);
+
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_ERROR_QUIT(Packet *p)
{
if (this->status < STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
diff --git a/src/network/network_client.h b/src/network/network_client.h
index 0674fd673..9a3c85491 100644
--- a/src/network/network_client.h
+++ b/src/network/network_client.h
@@ -57,6 +57,7 @@ protected:
NetworkRecvStatus Receive_SERVER_SYNC(Packet *p) override;
NetworkRecvStatus Receive_SERVER_COMMAND(Packet *p) override;
NetworkRecvStatus Receive_SERVER_CHAT(Packet *p) override;
+ NetworkRecvStatus Receive_SERVER_EXTERNAL_CHAT(Packet *p) override;
NetworkRecvStatus Receive_SERVER_QUIT(Packet *p) override;
NetworkRecvStatus Receive_SERVER_ERROR_QUIT(Packet *p) override;
NetworkRecvStatus Receive_SERVER_SHUTDOWN(Packet *p) override;
diff --git a/src/network/network_func.h b/src/network/network_func.h
index 1708ed95b..3ac4ae05f 100644
--- a/src/network/network_func.h
+++ b/src/network/network_func.h
@@ -78,6 +78,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_na
void NetworkServerDoMove(ClientID client_id, CompanyID company_id);
void NetworkServerSendRcon(ClientID client_id, TextColour colour_code, const std::string &string);
void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const std::string &msg, ClientID from_id, int64 data = 0, bool from_admin = false);
+void NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg);
void NetworkServerKickClient(ClientID client_id, const std::string &reason);
uint NetworkServerKickOrBanIP(ClientID client_id, bool ban, const std::string &reason);
diff --git a/src/network/network_internal.h b/src/network/network_internal.h
index f26f60a18..25240da5d 100644
--- a/src/network/network_internal.h
+++ b/src/network/network_internal.h
@@ -119,7 +119,7 @@ void NetworkFreeLocalCommandQueue();
void NetworkSyncCommandQueue(NetworkClientSocket *cs);
void ShowNetworkError(StringID error_string);
-void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0);
+void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, const std::string &name, const std::string &str = "", int64 data = 0, const std::string &data_str = "");
uint NetworkCalculateLag(const NetworkClientSocket *cs);
StringID GetNetworkErrorMsg(NetworkErrorCode err);
bool NetworkMakeClientNameUnique(std::string &new_name);
diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp
index cc2d748d9..9deaa5522 100644
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -671,6 +671,28 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendChat(NetworkAction action,
}
/**
+ * Send a chat message from external source.
+ * @param source Name of the source this message came from.
+ * @param colour TextColour to use for the message.
+ * @param user Name of the user who sent the messsage.
+ * @param msg The actual message.
+ */
+NetworkRecvStatus ServerNetworkGameSocketHandler::SendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
+{
+ if (this->status < STATUS_PRE_ACTIVE) return NETWORK_RECV_STATUS_OKAY;
+
+ Packet *p = new Packet(PACKET_SERVER_EXTERNAL_CHAT);
+
+ p->Send_string(source);
+ p->Send_uint16(colour);
+ p->Send_string(user);
+ p->Send_string(msg);
+
+ this->SendPacket(p);
+ return NETWORK_RECV_STATUS_OKAY;
+}
+
+/**
* Tell the client another client quit with an error.
* @param client_id The client that quit.
* @param errorno The reason the client quit.
@@ -1262,12 +1284,27 @@ void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, co
ci = NetworkClientInfo::GetByClientID(from_id);
if (ci != nullptr) {
- NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data);
+ NetworkTextMessage(action, GetDrawStringCompanyColour(ci->client_playas), false, ci->client_name, msg, data, "");
}
break;
}
}
+/**
+ * Send a chat message from external source.
+ * @param source Name of the source this message came from.
+ * @param colour TextColour to use for the message.
+ * @param user Name of the user who sent the messsage.
+ * @param msg The actual message.
+ */
+void NetworkServerSendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg)
+{
+ for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
+ cs->SendExternalChat(source, colour, user, msg);
+ }
+ NetworkTextMessage(NETWORK_ACTION_EXTERNAL_CHAT, colour, false, user, msg, 0, source);
+}
+
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_CHAT(Packet *p)
{
if (this->status < STATUS_PRE_ACTIVE) {
diff --git a/src/network/network_server.h b/src/network/network_server.h
index 419d1e6be..aaa83b962 100644
--- a/src/network/network_server.h
+++ b/src/network/network_server.h
@@ -93,6 +93,7 @@ public:
NetworkRecvStatus SendClientInfo(NetworkClientInfo *ci);
NetworkRecvStatus SendError(NetworkErrorCode error, const std::string &reason = {});
NetworkRecvStatus SendChat(NetworkAction action, ClientID client_id, bool self_send, const std::string &msg, int64 data);
+ NetworkRecvStatus SendExternalChat(const std::string &source, TextColour colour, const std::string &user, const std::string &msg);
NetworkRecvStatus SendJoin(ClientID client_id);
NetworkRecvStatus SendFrame();
NetworkRecvStatus SendSync();
diff --git a/src/network/network_type.h b/src/network/network_type.h
index 8564bef83..534f42c03 100644
--- a/src/network/network_type.h
+++ b/src/network/network_type.h
@@ -109,6 +109,7 @@ enum NetworkAction {
NETWORK_ACTION_COMPANY_JOIN,
NETWORK_ACTION_COMPANY_NEW,
NETWORK_ACTION_KICKED,
+ NETWORK_ACTION_EXTERNAL_CHAT,
};
/**