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