From 39f4a2f607d44738d60db84eba4b30e3d7450204 Mon Sep 17 00:00:00 2001 From: Pierre-Adrien Langrognet Date: Sun, 21 May 2017 23:06:51 +0200 Subject: [CSM] Add send_chat_message and run_server_chatcommand API functions (#5747) * [CSM] Add send_chat_message and run_server_chatcommand API functions * Add client-side chat message rate limiting * Limit out chat queue size * [CSM] Add minetest.clear_out_chat_queue API function and .clear_chat_queue chatcommand * Last fixes/cleanups before merge --- src/client.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) (limited to 'src/client.cpp') diff --git a/src/client.cpp b/src/client.cpp index a36f5413f..a5228132d 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -104,6 +104,8 @@ Client::Client( m_animation_time(0), m_crack_level(-1), m_crack_pos(0,0,0), + m_last_chat_message_sent(time(NULL)), + m_chat_message_allowance(5.0f), m_map_seed(0), m_password(password), m_chosen_auth_mech(AUTH_MECHANISM_NONE), @@ -400,6 +402,14 @@ void Client::step(float dtime) } } + /* + Send pending messages on out chat queue + */ + if (!m_out_chat_queue.empty() && canSendChatMessage()) { + sendChatMessage(m_out_chat_queue.front()); + m_out_chat_queue.pop(); + } + /* Handle environment */ @@ -1158,13 +1168,50 @@ void Client::sendInventoryAction(InventoryAction *a) Send(&pkt); } +bool Client::canSendChatMessage() const +{ + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + + float virt_chat_message_allowance = m_chat_message_allowance + time_passed * + (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f); + + if (virt_chat_message_allowance < 1.0f) + return false; + + return true; +} + void Client::sendChatMessage(const std::wstring &message) { - NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + const s16 max_queue_size = g_settings->getS16("max_out_chat_queue_size"); + if (canSendChatMessage()) { + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + m_last_chat_message_sent = time(NULL); - pkt << message; + m_chat_message_allowance += time_passed * (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f); + if (m_chat_message_allowance > CLIENT_CHAT_MESSAGE_LIMIT_PER_10S) + m_chat_message_allowance = CLIENT_CHAT_MESSAGE_LIMIT_PER_10S; - Send(&pkt); + m_chat_message_allowance -= 1.0f; + + NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16)); + + pkt << message; + + Send(&pkt); + } else if (m_out_chat_queue.size() < (u16) max_queue_size || max_queue_size == -1) { + m_out_chat_queue.push(message); + } else { + infostream << "Could not queue chat message because maximum out chat queue size (" + << max_queue_size << ") is reached." << std::endl; + } +} + +void Client::clearOutChatQueue() +{ + m_out_chat_queue = std::queue(); } void Client::sendChangePassword(const std::string &oldpassword, @@ -1924,4 +1971,3 @@ std::string Client::getModStoragePath() const { return porting::path_user + DIR_DELIM + "client" + DIR_DELIM + "mod_storage"; } - -- cgit v1.2.3