player_sao.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. Copyright (C) 2013-2020 Minetest core developers & community
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #pragma once
  18. #include "constants.h"
  19. #include "network/networkprotocol.h"
  20. #include "unit_sao.h"
  21. #include "util/numeric.h"
  22. /*
  23. PlayerSAO needs some internals exposed.
  24. */
  25. class LagPool
  26. {
  27. float m_pool = 15.0f;
  28. float m_max = 15.0f;
  29. public:
  30. LagPool() = default;
  31. void setMax(float new_max)
  32. {
  33. m_max = new_max;
  34. if (m_pool > new_max)
  35. m_pool = new_max;
  36. }
  37. void add(float dtime)
  38. {
  39. m_pool -= dtime;
  40. if (m_pool < 0)
  41. m_pool = 0;
  42. }
  43. void empty() { m_pool = m_max; }
  44. bool grab(float dtime)
  45. {
  46. if (dtime <= 0)
  47. return true;
  48. if (m_pool + dtime > m_max)
  49. return false;
  50. m_pool += dtime;
  51. return true;
  52. }
  53. };
  54. class RemotePlayer;
  55. class PlayerSAO : public UnitSAO
  56. {
  57. public:
  58. PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_,
  59. bool is_singleplayer);
  60. ActiveObjectType getType() const override { return ACTIVEOBJECT_TYPE_PLAYER; }
  61. ActiveObjectType getSendType() const override { return ACTIVEOBJECT_TYPE_GENERIC; }
  62. std::string getDescription() override;
  63. /*
  64. Active object <-> environment interface
  65. */
  66. void addedToEnvironment(u32 dtime_s) override;
  67. void removingFromEnvironment() override;
  68. bool isStaticAllowed() const override { return false; }
  69. bool shouldUnload() const override { return false; }
  70. std::string getClientInitializationData(u16 protocol_version) override;
  71. void getStaticData(std::string *result) const override;
  72. void step(float dtime, bool send_recommended) override;
  73. void setBasePosition(v3f position);
  74. void setPos(const v3f &pos) override;
  75. void moveTo(v3f pos, bool continuous) override;
  76. void setPlayerYaw(const float yaw);
  77. // Data should not be sent at player initialization
  78. void setPlayerYawAndSend(const float yaw);
  79. void setLookPitch(const float pitch);
  80. // Data should not be sent at player initialization
  81. void setLookPitchAndSend(const float pitch);
  82. f32 getLookPitch() const { return m_pitch; }
  83. f32 getRadLookPitch() const { return m_pitch * core::DEGTORAD; }
  84. // Deprecated
  85. f32 getRadLookPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; }
  86. void setFov(const float pitch);
  87. f32 getFov() const { return m_fov; }
  88. void setWantedRange(const s16 range);
  89. s16 getWantedRange() const { return m_wanted_range; }
  90. /*
  91. Interaction interface
  92. */
  93. u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
  94. float time_from_last_punch, u16 initial_wear = 0) override;
  95. void rightClick(ServerActiveObject *clicker) override;
  96. void setHP(s32 hp, const PlayerHPChangeReason &reason) override
  97. {
  98. return setHP(hp, reason, false);
  99. }
  100. void setHP(s32 hp, const PlayerHPChangeReason &reason, bool from_client);
  101. void setHPRaw(u16 hp) { m_hp = hp; }
  102. u16 getBreath() const { return m_breath; }
  103. void setBreath(const u16 breath, bool send = true);
  104. /*
  105. Inventory interface
  106. */
  107. Inventory *getInventory() const override;
  108. InventoryLocation getInventoryLocation() const override;
  109. void setInventoryModified() override {}
  110. std::string getWieldList() const override { return "main"; }
  111. u16 getWieldIndex() const override;
  112. ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const override;
  113. bool setWieldedItem(const ItemStack &item) override;
  114. /*
  115. PlayerSAO-specific
  116. */
  117. void disconnected();
  118. RemotePlayer *getPlayer() { return m_player; }
  119. session_t getPeerID() const { return m_peer_id; }
  120. // Cheat prevention
  121. v3f getLastGoodPosition() const { return m_last_good_position; }
  122. float resetTimeFromLastPunch()
  123. {
  124. float r = m_time_from_last_punch;
  125. m_time_from_last_punch = 0.0;
  126. return r;
  127. }
  128. void noCheatDigStart(const v3s16 &p)
  129. {
  130. m_nocheat_dig_pos = p;
  131. m_nocheat_dig_time = 0;
  132. }
  133. v3s16 getNoCheatDigPos() { return m_nocheat_dig_pos; }
  134. float getNoCheatDigTime() { return m_nocheat_dig_time; }
  135. void noCheatDigEnd() { m_nocheat_dig_pos = v3s16(32767, 32767, 32767); }
  136. LagPool &getDigPool() { return m_dig_pool; }
  137. void setMaxSpeedOverride(const v3f &vel);
  138. // Returns true if cheated
  139. bool checkMovementCheat();
  140. // Other
  141. void updatePrivileges(const std::set<std::string> &privs, bool is_singleplayer)
  142. {
  143. m_privs = privs;
  144. m_is_singleplayer = is_singleplayer;
  145. }
  146. bool getCollisionBox(aabb3f *toset) const override;
  147. bool getSelectionBox(aabb3f *toset) const override;
  148. bool collideWithObjects() const override { return true; }
  149. void finalize(RemotePlayer *player, const std::set<std::string> &privs);
  150. v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
  151. v3f getEyeOffset() const;
  152. float getZoomFOV() const;
  153. inline Metadata &getMeta() { return m_meta; }
  154. private:
  155. std::string getPropertyPacket();
  156. void unlinkPlayerSessionAndSave();
  157. std::string generateUpdatePhysicsOverrideCommand() const;
  158. RemotePlayer *m_player = nullptr;
  159. session_t m_peer_id = 0;
  160. // Cheat prevention
  161. LagPool m_dig_pool;
  162. LagPool m_move_pool;
  163. v3f m_last_good_position;
  164. float m_time_from_last_teleport = 0.0f;
  165. float m_time_from_last_punch = 0.0f;
  166. v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
  167. float m_nocheat_dig_time = 0.0f;
  168. float m_max_speed_override_time = 0.0f;
  169. v3f m_max_speed_override = v3f(0.0f, 0.0f, 0.0f);
  170. // Timers
  171. IntervalLimiter m_breathing_interval;
  172. IntervalLimiter m_drowning_interval;
  173. IntervalLimiter m_node_hurt_interval;
  174. bool m_position_not_sent = false;
  175. // Cached privileges for enforcement
  176. std::set<std::string> m_privs;
  177. bool m_is_singleplayer;
  178. u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
  179. f32 m_pitch = 0.0f;
  180. f32 m_fov = 0.0f;
  181. s16 m_wanted_range = 0.0f;
  182. Metadata m_meta;
  183. public:
  184. bool m_physics_override_sent = false;
  185. };
  186. struct PlayerHPChangeReason
  187. {
  188. enum Type : u8
  189. {
  190. SET_HP,
  191. SET_HP_MAX, // internal type to allow distinguishing hp reset and damage (for effects)
  192. PLAYER_PUNCH,
  193. FALL,
  194. NODE_DAMAGE,
  195. DROWNING,
  196. RESPAWN
  197. };
  198. Type type = SET_HP;
  199. bool from_mod = false;
  200. int lua_reference = -1;
  201. // For PLAYER_PUNCH
  202. ServerActiveObject *object = nullptr;
  203. // For NODE_DAMAGE
  204. std::string node;
  205. inline bool hasLuaReference() const { return lua_reference >= 0; }
  206. bool setTypeFromString(const std::string &typestr)
  207. {
  208. if (typestr == "set_hp")
  209. type = SET_HP;
  210. else if (typestr == "punch")
  211. type = PLAYER_PUNCH;
  212. else if (typestr == "fall")
  213. type = FALL;
  214. else if (typestr == "node_damage")
  215. type = NODE_DAMAGE;
  216. else if (typestr == "drown")
  217. type = DROWNING;
  218. else if (typestr == "respawn")
  219. type = RESPAWN;
  220. else
  221. return false;
  222. return true;
  223. }
  224. std::string getTypeAsString() const
  225. {
  226. switch (type) {
  227. case PlayerHPChangeReason::SET_HP:
  228. case PlayerHPChangeReason::SET_HP_MAX:
  229. return "set_hp";
  230. case PlayerHPChangeReason::PLAYER_PUNCH:
  231. return "punch";
  232. case PlayerHPChangeReason::FALL:
  233. return "fall";
  234. case PlayerHPChangeReason::NODE_DAMAGE:
  235. return "node_damage";
  236. case PlayerHPChangeReason::DROWNING:
  237. return "drown";
  238. case PlayerHPChangeReason::RESPAWN:
  239. return "respawn";
  240. default:
  241. return "?";
  242. }
  243. }
  244. PlayerHPChangeReason(Type type) : type(type) {}
  245. PlayerHPChangeReason(Type type, ServerActiveObject *object) :
  246. type(type), object(object)
  247. {
  248. }
  249. PlayerHPChangeReason(Type type, std::string node) : type(type), node(node) {}
  250. };