diff options
author | Pierre-Adrien Langrognet <upsilon@langg.net> | 2017-05-21 23:06:51 +0200 |
---|---|---|
committer | Loïc Blot <nerzhul@users.noreply.github.com> | 2017-05-21 23:06:51 +0200 |
commit | 39f4a2f607d44738d60db84eba4b30e3d7450204 (patch) | |
tree | 63a72301d3c53917b99fe0607f48219372f85b6f /src | |
parent | ec490abf5889e06c88887e17f1746043de3b10fe (diff) | |
download | minetest-39f4a2f607d44738d60db84eba4b30e3d7450204.tar.gz minetest-39f4a2f607d44738d60db84eba4b30e3d7450204.tar.bz2 minetest-39f4a2f607d44738d60db84eba4b30e3d7450204.zip |
[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
Diffstat (limited to 'src')
-rw-r--r-- | src/client.cpp | 54 | ||||
-rw-r--r-- | src/client.h | 8 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 1 | ||||
-rw-r--r-- | src/script/lua_api/l_client.cpp | 19 | ||||
-rw-r--r-- | src/script/lua_api/l_client.h | 6 |
5 files changed, 84 insertions, 4 deletions
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), @@ -401,6 +403,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 */ // Control local player (0ms) @@ -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<std::wstring>(); } 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"; } - diff --git a/src/client.h b/src/client.h index cc0d4699d..b4145c76f 100644 --- a/src/client.h +++ b/src/client.h @@ -38,6 +38,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "tileanimation.h" #include "mesh_generator_thread.h" +#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f + struct MeshMakeData; class MapBlockMesh; class IWritableTextureSource; @@ -360,6 +362,7 @@ public: const StringMap &fields); void sendInventoryAction(InventoryAction *a); void sendChatMessage(const std::wstring &message); + void clearOutChatQueue(); void sendChangePassword(const std::string &oldpassword, const std::string &newpassword); void sendDamage(u8 damage); @@ -565,6 +568,8 @@ private: inline std::string getPlayerName() { return m_env.getLocalPlayer()->getName(); } + bool canSendChatMessage() const; + float m_packetcounter_timer; float m_connection_reinit_timer; float m_avg_rtt_timer; @@ -612,6 +617,9 @@ private: //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; // The authentication methods we can use to enter sudo mode (=change password) u32 m_sudo_auth_methods; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index c583220bd..0a44069fd 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -57,6 +57,7 @@ void set_default_settings(Settings *settings) settings->setDefault("curl_verify_cert", "true"); settings->setDefault("enable_remote_media_server", "true"); settings->setDefault("enable_client_modding", "false"); + settings->setDefault("max_out_chat_queue_size", "20"); // Keymap settings->setDefault("remote_port", "30000"); diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 09b832ccf..0b7450af2 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -85,6 +85,23 @@ int ModApiClient::l_display_chat_message(lua_State *L) return 1; } +// send_chat_message(message) +int ModApiClient::l_send_chat_message(lua_State *L) +{ + if (!lua_isstring(L,1)) + return 0; + std::string message = luaL_checkstring(L, 1); + getClient(L)->sendChatMessage(utf8_to_wide(message)); + return 0; +} + +// clear_out_chat_queue() +int ModApiClient::l_clear_out_chat_queue(lua_State *L) +{ + getClient(L)->clearOutChatQueue(); + return 0; +} + // get_player_names() int ModApiClient::l_get_player_names(lua_State *L) { @@ -317,6 +334,8 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_current_modname); API_FCT(print); API_FCT(display_chat_message); + API_FCT(send_chat_message); + API_FCT(clear_out_chat_queue); API_FCT(get_player_names); API_FCT(set_last_run_mod); API_FCT(get_last_run_mod); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 09b74addd..fe5780fb1 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -37,6 +37,12 @@ private: // display_chat_message(message) static int l_display_chat_message(lua_State *L); + // send_chat_message(message) + static int l_send_chat_message(lua_State *L); + + // clear_out_chat_queue() + static int l_clear_out_chat_queue(lua_State *L); + // get_player_names() static int l_get_player_names(lua_State *L); |