diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/clientiface.cpp | 2 | ||||
-rw-r--r-- | src/content_sao.cpp | 6 | ||||
-rw-r--r-- | src/content_sao.h | 5 | ||||
-rw-r--r-- | src/environment.cpp | 2 | ||||
-rw-r--r-- | src/environment.h | 2 | ||||
-rw-r--r-- | src/localplayer.h | 1 | ||||
-rw-r--r-- | src/player.cpp | 206 | ||||
-rw-r--r-- | src/player.h | 149 | ||||
-rw-r--r-- | src/remoteplayer.cpp | 230 | ||||
-rw-r--r-- | src/remoteplayer.h | 175 | ||||
-rw-r--r-- | src/script/lua_api/l_object.cpp | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_object.h | 2 | ||||
-rw-r--r-- | src/server.cpp | 8 | ||||
-rw-r--r-- | src/server.h | 2 |
15 files changed, 423 insertions, 370 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 753291cba..8e3ae95ab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -445,6 +445,7 @@ set(common_SRCS porting.cpp profiler.cpp quicktune.cpp + remoteplayer.cpp rollback.cpp rollback_interface.cpp serialization.cpp diff --git a/src/clientiface.cpp b/src/clientiface.cpp index fbfc16770..d78cf1c53 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientiface.h" #include "util/numeric.h" #include "util/mathconstants.h" -#include "player.h" +#include "remoteplayer.h" #include "settings.h" #include "mapblock.h" #include "network/connection.h" diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 1664f5993..5d3ed38bc 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" // For compressZlib #include "tool.h" // For ToolCapabilities #include "gamedef.h" -#include "player.h" +#include "remoteplayer.h" #include "server.h" #include "scripting_game.h" #include "genericobject.h" @@ -391,7 +391,7 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 - for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); + for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); (ii != m_attachment_child_ids.end()); ++ii) { if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version))); @@ -880,7 +880,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, m_physics_override_sneak_glitch)); // 5 os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6 (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only. - for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); + for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); ii != m_attachment_child_ids.end(); ++ii) { if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version))); diff --git a/src/content_sao.h b/src/content_sao.h index 341ebb5da..76a3a37da 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include "itemgroup.h" -#include "player.h" #include "object_properties.h" /* @@ -157,6 +156,8 @@ public: } }; +class RemotePlayer; + class PlayerSAO : public ServerActiveObject { public: @@ -231,7 +232,7 @@ public: void disconnected(); - RemotePlayer* getPlayer() { return m_player; } + RemotePlayer *getPlayer() { return m_player; } u16 getPeerID() const { return m_peer_id; } // Cheat prevention diff --git a/src/environment.cpp b/src/environment.cpp index 514aa918a..ff43ac516 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2705,7 +2705,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) } object->setId(new_id); } - if(!isFreeClientActiveObjectId(object->getId(), m_active_objects)) { + if (!isFreeClientActiveObjectId(object->getId(), m_active_objects)) { infostream<<"ClientEnvironment::addActiveObject(): " <<"id is not free ("<<object->getId()<<")"<<std::endl; delete object; diff --git a/src/environment.h b/src/environment.h index 7ed38ad5d..f19708ad7 100644 --- a/src/environment.h +++ b/src/environment.h @@ -377,7 +377,7 @@ public: Find out what new objects have been removed from inside a radius around a position */ - void getRemovedActiveObjects(RemotePlayer* player, s16 radius, + void getRemovedActiveObjects(RemotePlayer *player, s16 radius, s16 player_radius, std::set<u16> ¤t_objects, std::queue<u16> &removed_objects); diff --git a/src/localplayer.h b/src/localplayer.h index 182b51d4d..9d43128aa 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -28,6 +28,7 @@ class Client; class Environment; class GenericCAO; class ClientActiveObject; +class IGameDef; enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local animation, walking, digging, both diff --git a/src/player.cpp b/src/player.cpp index c0d367134..fa82a79f4 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -19,15 +19,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" -#include <fstream> #include "threading/mutex_auto_lock.h" #include "util/numeric.h" #include "hud.h" #include "constants.h" #include "gamedef.h" #include "settings.h" -#include "content_sao.h" -#include "filesys.h" #include "log.h" #include "porting.h" // strlcpy @@ -143,206 +140,3 @@ void Player::clearHud() hud.pop_back(); } } - -/* - RemotePlayer -*/ -// static config cache for remoteplayer -bool RemotePlayer::m_setting_cache_loaded = false; -float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f; -u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0; - -RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef): - Player(name, idef), - protocol_version(0), - m_sao(NULL), - m_dirty(false), - m_last_chat_message_sent(time(NULL)), - m_chat_message_allowance(5.0f), - m_message_rate_overhead(0), - hud_hotbar_image(""), - hud_hotbar_selected_image("") -{ - if (!RemotePlayer::m_setting_cache_loaded) { - RemotePlayer::m_setting_chat_message_limit_per_10sec = - g_settings->getFloat("chat_message_limit_per_10sec"); - RemotePlayer::m_setting_chat_message_limit_trigger_kick = - g_settings->getU16("chat_message_limit_trigger_kick"); - RemotePlayer::m_setting_cache_loaded = true; - } - movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS; - movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS; - movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS; - movement_speed_walk = g_settings->getFloat("movement_speed_walk") * BS; - movement_speed_crouch = g_settings->getFloat("movement_speed_crouch") * BS; - movement_speed_fast = g_settings->getFloat("movement_speed_fast") * BS; - movement_speed_climb = g_settings->getFloat("movement_speed_climb") * BS; - movement_speed_jump = g_settings->getFloat("movement_speed_jump") * BS; - movement_liquid_fluidity = g_settings->getFloat("movement_liquid_fluidity") * BS; - movement_liquid_fluidity_smooth = g_settings->getFloat("movement_liquid_fluidity_smooth") * BS; - movement_liquid_sink = g_settings->getFloat("movement_liquid_sink") * BS; - movement_gravity = g_settings->getFloat("movement_gravity") * BS; -} - -void RemotePlayer::save(std::string savedir, IGameDef *gamedef) -{ - /* - * We have to open all possible player files in the players directory - * and check their player names because some file systems are not - * case-sensitive and player names are case-sensitive. - */ - - // A player to deserialize files into to check their names - RemotePlayer testplayer("", gamedef->idef()); - - savedir += DIR_DELIM; - std::string path = savedir + m_name; - for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) { - if (!fs::PathExists(path)) { - // Open file and serialize - std::ostringstream ss(std::ios_base::binary); - serialize(ss); - if (!fs::safeWriteToFile(path, ss.str())) { - infostream << "Failed to write " << path << std::endl; - } - setModified(false); - return; - } - // Open file and deserialize - std::ifstream is(path.c_str(), std::ios_base::binary); - if (!is.good()) { - infostream << "Failed to open " << path << std::endl; - return; - } - testplayer.deSerialize(is, path); - is.close(); - if (strcmp(testplayer.getName(), m_name) == 0) { - // Open file and serialize - std::ostringstream ss(std::ios_base::binary); - serialize(ss); - if (!fs::safeWriteToFile(path, ss.str())) { - infostream << "Failed to write " << path << std::endl; - } - setModified(false); - return; - } - path = savedir + m_name + itos(i); - } - - infostream << "Didn't find free file for player " << m_name << std::endl; - return; -} - -void RemotePlayer::deSerialize(std::istream &is, const std::string &playername) -{ - Settings args; - - if (!args.parseConfigLines(is, "PlayerArgsEnd")) { - throw SerializationError("PlayerArgsEnd of player " + - playername + " not found!"); - } - - m_dirty = true; - //args.getS32("version"); // Version field value not used - std::string name = args.get("name"); - strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); - setPitch(args.getFloat("pitch")); - setYaw(args.getFloat("yaw")); - setPosition(args.getV3F("position")); - try{ - hp = args.getS32("hp"); - }catch(SettingNotFoundException &e) { - hp = PLAYER_MAX_HP; - } - try{ - m_breath = args.getS32("breath"); - }catch(SettingNotFoundException &e) { - m_breath = PLAYER_MAX_BREATH; - } - - inventory.deSerialize(is); - - if(inventory.getList("craftpreview") == NULL) { - // Convert players without craftpreview - inventory.addList("craftpreview", 1); - - bool craftresult_is_preview = true; - if(args.exists("craftresult_is_preview")) - craftresult_is_preview = args.getBool("craftresult_is_preview"); - if(craftresult_is_preview) - { - // Clear craftresult - inventory.getList("craftresult")->changeItem(0, ItemStack()); - } - } -} - -void RemotePlayer::serialize(std::ostream &os) -{ - // Utilize a Settings object for storing values - Settings args; - args.setS32("version", 1); - args.set("name", m_name); - //args.set("password", m_password); - args.setFloat("pitch", m_pitch); - args.setFloat("yaw", m_yaw); - args.setV3F("position", m_position); - args.setS32("hp", hp); - args.setS32("breath", m_breath); - - args.writeLines(os); - - os<<"PlayerArgsEnd\n"; - - inventory.serialize(os); -} - -void RemotePlayer::setPosition(const v3f &position) -{ - if (position != m_position) - m_dirty = true; - - Player::setPosition(position); - if(m_sao) - m_sao->setBasePosition(position); -} - -const RemotePlayerChatResult RemotePlayer::canSendChatMessage() -{ - // Rate limit messages - u32 now = time(NULL); - float time_passed = now - m_last_chat_message_sent; - m_last_chat_message_sent = now; - - // If this feature is disabled - if (m_setting_chat_message_limit_per_10sec <= 0.0) { - return RPLAYER_CHATRESULT_OK; - } - - m_chat_message_allowance += time_passed * (m_setting_chat_message_limit_per_10sec / 8.0f); - if (m_chat_message_allowance > m_setting_chat_message_limit_per_10sec) { - m_chat_message_allowance = m_setting_chat_message_limit_per_10sec; - } - - if (m_chat_message_allowance < 1.0f) { - infostream << "Player " << m_name - << " chat limited due to excessive message amount." << std::endl; - - // Kick player if flooding is too intensive - m_message_rate_overhead++; - if (m_message_rate_overhead > RemotePlayer::m_setting_chat_message_limit_trigger_kick) { - return RPLAYER_CHATRESULT_KICK; - } - - return RPLAYER_CHATRESULT_FLOODING; - } - - // Reinit message overhead - if (m_message_rate_overhead > 0) { - m_message_rate_overhead = 0; - } - - m_chat_message_allowance -= 1.0f; - return RPLAYER_CHATRESULT_OK; -} - diff --git a/src/player.h b/src/player.h index 1980a86a3..3c945b100 100644 --- a/src/player.h +++ b/src/player.h @@ -99,9 +99,7 @@ struct PlayerControl }; class Map; -class IGameDef; struct CollisionInfo; -class PlayerSAO; struct HudElement; class Environment; @@ -258,152 +256,5 @@ private: Mutex m_mutex; }; -enum RemotePlayerChatResult { - RPLAYER_CHATRESULT_OK, - RPLAYER_CHATRESULT_FLOODING, - RPLAYER_CHATRESULT_KICK, -}; -/* - Player on the server -*/ -class RemotePlayer : public Player -{ -public: - RemotePlayer(const char *name, IItemDefManager *idef); - virtual ~RemotePlayer() {} - - void save(std::string savedir, IGameDef *gamedef); - void deSerialize(std::istream &is, const std::string &playername); - - PlayerSAO *getPlayerSAO() { return m_sao; } - void setPlayerSAO(PlayerSAO *sao) { m_sao = sao; } - void setPosition(const v3f &position); - - const RemotePlayerChatResult canSendChatMessage(); - - void setHotbarItemcount(s32 hotbar_itemcount) - { - hud_hotbar_itemcount = hotbar_itemcount; - } - - s32 getHotbarItemcount() const { return hud_hotbar_itemcount; } - - void overrideDayNightRatio(bool do_override, float ratio) - { - m_day_night_ratio_do_override = do_override; - m_day_night_ratio = ratio; - } - - void getDayNightRatio(bool *do_override, float *ratio) - { - *do_override = m_day_night_ratio_do_override; - *ratio = m_day_night_ratio; - } - - // Use a function, if isDead can be defined by other conditions - bool isDead() const { return hp == 0; } - - void setHotbarImage(const std::string &name) - { - hud_hotbar_image = name; - } - - std::string getHotbarImage() const - { - return hud_hotbar_image; - } - - void setHotbarSelectedImage(const std::string &name) - { - hud_hotbar_selected_image = name; - } - - const std::string &getHotbarSelectedImage() const - { - return hud_hotbar_selected_image; - } - - // Deprecated - f32 getRadPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; } - - // Deprecated - f32 getRadYawDep() const { return (m_yaw + 90.) * core::DEGTORAD; } - - void setSky(const video::SColor &bgcolor, const std::string &type, - const std::vector<std::string> ¶ms) - { - m_sky_bgcolor = bgcolor; - m_sky_type = type; - m_sky_params = params; - } - - void getSky(video::SColor *bgcolor, std::string *type, - std::vector<std::string> *params) - { - *bgcolor = m_sky_bgcolor; - *type = m_sky_type; - *params = m_sky_params; - } - - bool checkModified() const { return m_dirty || inventory.checkModified(); } - - void setModified(const bool x) - { - m_dirty = x; - if (!x) - inventory.setModified(x); - } - - virtual void setBreath(u16 breath) - { - if (breath != m_breath) - m_dirty = true; - Player::setBreath(breath); - } - - virtual void setPitch(f32 pitch) - { - if (pitch != m_pitch) - m_dirty = true; - Player::setPitch(pitch); - } - - virtual void setYaw(f32 yaw) - { - if (yaw != m_yaw) - m_dirty = true; - Player::setYaw(yaw); - } - - u16 protocol_version; -private: - /* - serialize() writes a bunch of text that can contain - any characters except a '\0', and such an ending that - deSerialize stops reading exactly at the right point. - */ - void serialize(std::ostream &os); - - PlayerSAO *m_sao; - bool m_dirty; - - static bool m_setting_cache_loaded; - static float m_setting_chat_message_limit_per_10sec; - static u16 m_setting_chat_message_limit_trigger_kick; - - u32 m_last_chat_message_sent; - float m_chat_message_allowance; - u16 m_message_rate_overhead; - - bool m_day_night_ratio_do_override; - float m_day_night_ratio; - std::string hud_hotbar_image; - std::string hud_hotbar_selected_image; - - std::string m_sky_type; - video::SColor m_sky_bgcolor; - std::vector<std::string> m_sky_params; -}; - #endif diff --git a/src/remoteplayer.cpp b/src/remoteplayer.cpp new file mode 100644 index 000000000..f64d1d690 --- /dev/null +++ b/src/remoteplayer.cpp @@ -0,0 +1,230 @@ +/* +Minetest +Copyright (C) 2010-2016 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2014-2016 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. +*/ + +#include "remoteplayer.h" +#include "content_sao.h" +#include "filesys.h" +#include "gamedef.h" +#include "porting.h" // strlcpy +#include "settings.h" + + +/* + RemotePlayer +*/ +// static config cache for remoteplayer +bool RemotePlayer::m_setting_cache_loaded = false; +float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f; +u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0; + +RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef): + Player(name, idef), + protocol_version(0), + m_sao(NULL), + m_dirty(false), + m_last_chat_message_sent(time(NULL)), + m_chat_message_allowance(5.0f), + m_message_rate_overhead(0), + hud_hotbar_image(""), + hud_hotbar_selected_image("") +{ + if (!RemotePlayer::m_setting_cache_loaded) { + RemotePlayer::m_setting_chat_message_limit_per_10sec = + g_settings->getFloat("chat_message_limit_per_10sec"); + RemotePlayer::m_setting_chat_message_limit_trigger_kick = + g_settings->getU16("chat_message_limit_trigger_kick"); + RemotePlayer::m_setting_cache_loaded = true; + } + movement_acceleration_default = g_settings->getFloat("movement_acceleration_default") * BS; + movement_acceleration_air = g_settings->getFloat("movement_acceleration_air") * BS; + movement_acceleration_fast = g_settings->getFloat("movement_acceleration_fast") * BS; + movement_speed_walk = g_settings->getFloat("movement_speed_walk") * BS; + movement_speed_crouch = g_settings->getFloat("movement_speed_crouch") * BS; + movement_speed_fast = g_settings->getFloat("movement_speed_fast") * BS; + movement_speed_climb = g_settings->getFloat("movement_speed_climb") * BS; + movement_speed_jump = g_settings->getFloat("movement_speed_jump") * BS; + movement_liquid_fluidity = g_settings->getFloat("movement_liquid_fluidity") * BS; + movement_liquid_fluidity_smooth = g_settings->getFloat("movement_liquid_fluidity_smooth") * BS; + movement_liquid_sink = g_settings->getFloat("movement_liquid_sink") * BS; + movement_gravity = g_settings->getFloat("movement_gravity") * BS; +} + +void RemotePlayer::save(std::string savedir, IGameDef *gamedef) +{ + /* + * We have to open all possible player files in the players directory + * and check their player names because some file systems are not + * case-sensitive and player names are case-sensitive. + */ + + // A player to deserialize files into to check their names + RemotePlayer testplayer("", gamedef->idef()); + + savedir += DIR_DELIM; + std::string path = savedir + m_name; + for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) { + if (!fs::PathExists(path)) { + // Open file and serialize + std::ostringstream ss(std::ios_base::binary); + serialize(ss); + if (!fs::safeWriteToFile(path, ss.str())) { + infostream << "Failed to write " << path << std::endl; + } + setModified(false); + return; + } + // Open file and deserialize + std::ifstream is(path.c_str(), std::ios_base::binary); + if (!is.good()) { + infostream << "Failed to open " << path << std::endl; + return; + } + testplayer.deSerialize(is, path); + is.close(); + if (strcmp(testplayer.getName(), m_name) == 0) { + // Open file and serialize + std::ostringstream ss(std::ios_base::binary); + serialize(ss); + if (!fs::safeWriteToFile(path, ss.str())) { + infostream << "Failed to write " << path << std::endl; + } + setModified(false); + return; + } + path = savedir + m_name + itos(i); + } + + infostream << "Didn't find free file for player " << m_name << std::endl; + return; +} + +void RemotePlayer::deSerialize(std::istream &is, const std::string &playername) +{ + Settings args; + + if (!args.parseConfigLines(is, "PlayerArgsEnd")) { + throw SerializationError("PlayerArgsEnd of player " + + playername + " not found!"); + } + + m_dirty = true; + //args.getS32("version"); // Version field value not used + std::string name = args.get("name"); + strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); + setPitch(args.getFloat("pitch")); + setYaw(args.getFloat("yaw")); + setPosition(args.getV3F("position")); + try { + hp = args.getS32("hp"); + } catch(SettingNotFoundException &e) { + hp = PLAYER_MAX_HP; + } + + try { + m_breath = args.getS32("breath"); + } catch(SettingNotFoundException &e) { + m_breath = PLAYER_MAX_BREATH; + } + + inventory.deSerialize(is); + + if(inventory.getList("craftpreview") == NULL) { + // Convert players without craftpreview + inventory.addList("craftpreview", 1); + + bool craftresult_is_preview = true; + if(args.exists("craftresult_is_preview")) + craftresult_is_preview = args.getBool("craftresult_is_preview"); + if(craftresult_is_preview) + { + // Clear craftresult + inventory.getList("craftresult")->changeItem(0, ItemStack()); + } + } +} + +void RemotePlayer::serialize(std::ostream &os) +{ + // Utilize a Settings object for storing values + Settings args; + args.setS32("version", 1); + args.set("name", m_name); + //args.set("password", m_password); + args.setFloat("pitch", m_pitch); + args.setFloat("yaw", m_yaw); + args.setV3F("position", m_position); + args.setS32("hp", hp); + args.setS32("breath", m_breath); + + args.writeLines(os); + + os<<"PlayerArgsEnd\n"; + + inventory.serialize(os); +} + +void RemotePlayer::setPosition(const v3f &position) +{ + if (position != m_position) + m_dirty = true; + + Player::setPosition(position); + if(m_sao) + m_sao->setBasePosition(position); +} + +const RemotePlayerChatResult RemotePlayer::canSendChatMessage() +{ + // Rate limit messages + u32 now = time(NULL); + float time_passed = now - m_last_chat_message_sent; + m_last_chat_message_sent = now; + + // If this feature is disabled + if (m_setting_chat_message_limit_per_10sec <= 0.0) { + return RPLAYER_CHATRESULT_OK; + } + + m_chat_message_allowance += time_passed * (m_setting_chat_message_limit_per_10sec / 8.0f); + if (m_chat_message_allowance > m_setting_chat_message_limit_per_10sec) { + m_chat_message_allowance = m_setting_chat_message_limit_per_10sec; + } + + if (m_chat_message_allowance < 1.0f) { + infostream << "Player " << m_name + << " chat limited due to excessive message amount." << std::endl; + + // Kick player if flooding is too intensive + m_message_rate_overhead++; + if (m_message_rate_overhead > RemotePlayer::m_setting_chat_message_limit_trigger_kick) { + return RPLAYER_CHATRESULT_KICK; + } + + return RPLAYER_CHATRESULT_FLOODING; + } + + // Reinit message overhead + if (m_message_rate_overhead > 0) { + m_message_rate_overhead = 0; + } + + m_chat_message_allowance -= 1.0f; + return RPLAYER_CHATRESULT_OK; +} diff --git a/src/remoteplayer.h b/src/remoteplayer.h new file mode 100644 index 000000000..f6c70b0e9 --- /dev/null +++ b/src/remoteplayer.h @@ -0,0 +1,175 @@ +/* +Minetest +Copyright (C) 2010-2016 celeron55, Perttu Ahola <celeron55@gmail.com> +Copyright (C) 2014-2016 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 REMOTEPLAYER_HEADER +#define REMOTEPLAYER_HEADER + +#include "player.h" + +class PlayerSAO; + +enum RemotePlayerChatResult { + RPLAYER_CHATRESULT_OK, + RPLAYER_CHATRESULT_FLOODING, + RPLAYER_CHATRESULT_KICK, +}; +/* + Player on the server +*/ +class RemotePlayer : public Player +{ +public: + RemotePlayer(const char *name, IItemDefManager *idef); + virtual ~RemotePlayer() {} + + void save(std::string savedir, IGameDef *gamedef); + void deSerialize(std::istream &is, const std::string &playername); + + PlayerSAO *getPlayerSAO() { return m_sao; } + void setPlayerSAO(PlayerSAO *sao) { m_sao = sao; } + void setPosition(const v3f &position); + + const RemotePlayerChatResult canSendChatMessage(); + + void setHotbarItemcount(s32 hotbar_itemcount) + { + hud_hotbar_itemcount = hotbar_itemcount; + } + + s32 getHotbarItemcount() const { return hud_hotbar_itemcount; } + + void overrideDayNightRatio(bool do_override, float ratio) + { + m_day_night_ratio_do_override = do_override; + m_day_night_ratio = ratio; + } + + void getDayNightRatio(bool *do_override, float *ratio) + { + *do_override = m_day_night_ratio_do_override; + *ratio = m_day_night_ratio; + } + + // Use a function, if isDead can be defined by other conditions + bool isDead() const { return hp == 0; } + + void setHotbarImage(const std::string &name) + { + hud_hotbar_image = name; + } + + std::string getHotbarImage() const + { + return hud_hotbar_image; + } + + void setHotbarSelectedImage(const std::string &name) + { + hud_hotbar_selected_image = name; + } + + const std::string &getHotbarSelectedImage() const + { + return hud_hotbar_selected_image; + } + + // Deprecated + f32 getRadPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; } + + // Deprecated + f32 getRadYawDep() const { return (m_yaw + 90.) * core::DEGTORAD; } + + void setSky(const video::SColor &bgcolor, const std::string &type, + const std::vector<std::string> ¶ms) + { + m_sky_bgcolor = bgcolor; + m_sky_type = type; + m_sky_params = params; + } + + void getSky(video::SColor *bgcolor, std::string *type, + std::vector<std::string> *params) + { + *bgcolor = m_sky_bgcolor; + *type = m_sky_type; + *params = m_sky_params; + } + + bool checkModified() const { return m_dirty || inventory.checkModified(); } + + void setModified(const bool x) + { + m_dirty = x; + if (!x) + inventory.setModified(x); + } + + virtual void setBreath(u16 breath) + { + if (breath != m_breath) + m_dirty = true; + Player::setBreath(breath); + } + + virtual void setPitch(f32 pitch) + { + if (pitch != m_pitch) + m_dirty = true; + Player::setPitch(pitch); + } + + virtual void setYaw(f32 yaw) + { + if (yaw != m_yaw) + m_dirty = true; + Player::setYaw(yaw); + } + + u16 protocol_version; +private: + /* + serialize() writes a bunch of text that can contain + any characters except a '\0', and such an ending that + deSerialize stops reading exactly at the right point. + */ + void serialize(std::ostream &os); + + PlayerSAO *m_sao; + bool m_dirty; + + static bool m_setting_cache_loaded; + static float m_setting_chat_message_limit_per_10sec; + static u16 m_setting_chat_message_limit_trigger_kick; + + u32 m_last_chat_message_sent; + float m_chat_message_allowance; + u16 m_message_rate_overhead; + + bool m_day_night_ratio_do_override; + float m_day_night_ratio; + std::string hud_hotbar_image; + std::string hud_hotbar_selected_image; + + std::string m_sky_type; + video::SColor m_sky_bgcolor; + std::vector<std::string> m_sky_params; +}; + +#endif diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index a1f83919c..bb352e429 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -107,7 +107,7 @@ PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref) return (PlayerSAO*)obj; } -RemotePlayer* ObjectRef::getplayer(ObjectRef *ref) +RemotePlayer *ObjectRef::getplayer(ObjectRef *ref) { PlayerSAO *playersao = getplayersao(ref); if (playersao == NULL) diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index dfc1b49d2..09f10e417 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -47,7 +47,7 @@ private: static PlayerSAO* getplayersao(ObjectRef *ref); - static RemotePlayer* getplayer(ObjectRef *ref); + static RemotePlayer *getplayer(ObjectRef *ref); // Exported functions diff --git a/src/server.cpp b/src/server.cpp index 71e71f43e..a93c143c7 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2688,7 +2688,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason) SendChatMessage(PEER_ID_INEXISTENT,message); } -void Server::UpdateCrafting(RemotePlayer* player) +void Server::UpdateCrafting(RemotePlayer *player) { DSTACK(FUNCTION_NAME); @@ -3141,7 +3141,7 @@ void Server::spawnParticle(const std::string &playername, v3f pos, u16 peer_id = PEER_ID_INEXISTENT; if (playername != "") { - RemotePlayer* player = m_env->getPlayer(playername.c_str()); + RemotePlayer *player = m_env->getPlayer(playername.c_str()); if (!player) return; peer_id = player->peer_id; @@ -3165,7 +3165,7 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime, u16 peer_id = PEER_ID_INEXISTENT; if (playername != "") { - RemotePlayer* player = m_env->getPlayer(playername.c_str()); + RemotePlayer *player = m_env->getPlayer(playername.c_str()); if (!player) return -1; peer_id = player->peer_id; @@ -3188,7 +3188,7 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id) u16 peer_id = PEER_ID_INEXISTENT; if (playername != "") { - RemotePlayer* player = m_env->getPlayer(playername.c_str()); + RemotePlayer *player = m_env->getPlayer(playername.c_str()); if (!player) return; peer_id = player->peer_id; diff --git a/src/server.h b/src/server.h index fc4758c5f..6ee61a0eb 100644 --- a/src/server.h +++ b/src/server.h @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "chat_interface.h" #include "clientiface.h" -#include "player.h" +#include "remoteplayer.h" #include "network/networkpacket.h" #include <string> #include <list> |