]> git.lizzy.rs Git - minetest.git/blob - src/server/player_sao.h
Physics overrides: Move values to a common struct (#12591)
[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 override { return ACTIVEOBJECT_TYPE_PLAYER; }
76         ActiveObjectType getSendType() const override { return ACTIVEOBJECT_TYPE_GENERIC; }
77         std::string getDescription() override;
78
79         /*
80                 Active object <-> environment interface
81         */
82
83         void addedToEnvironment(u32 dtime_s) override;
84         void removingFromEnvironment() override;
85         bool isStaticAllowed() const override { return false; }
86         bool shouldUnload() const override { return false; }
87         std::string getClientInitializationData(u16 protocol_version) override;
88         void getStaticData(std::string *result) const override;
89         void step(float dtime, bool send_recommended) override;
90         void setBasePosition(v3f position);
91         void setPos(const v3f &pos) override;
92         void moveTo(v3f pos, bool continuous) override;
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         u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
113                         float time_from_last_punch, u16 initial_wear = 0) override;
114         void rightClick(ServerActiveObject *clicker) override;
115         void setHP(s32 hp, const PlayerHPChangeReason &reason) override
116         {
117                 return setHP(hp, reason, false);
118         }
119         void setHP(s32 hp, const PlayerHPChangeReason &reason, bool from_client);
120         void setHPRaw(u16 hp) { m_hp = hp; }
121         u16 getBreath() const { return m_breath; }
122         void setBreath(const u16 breath, bool send = true);
123
124         /*
125                 Inventory interface
126         */
127         Inventory *getInventory() const override;
128         InventoryLocation getInventoryLocation() const override;
129         void setInventoryModified() override {}
130         std::string getWieldList() const override { return "main"; }
131         u16 getWieldIndex() const override;
132         ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const override;
133         bool setWieldedItem(const ItemStack &item) override;
134
135         /*
136                 PlayerSAO-specific
137         */
138
139         void disconnected();
140
141         RemotePlayer *getPlayer() { return m_player; }
142         session_t getPeerID() const { return m_peer_id; }
143
144         // Cheat prevention
145
146         v3f getLastGoodPosition() const { return m_last_good_position; }
147         float resetTimeFromLastPunch()
148         {
149                 float r = m_time_from_last_punch;
150                 m_time_from_last_punch = 0.0;
151                 return r;
152         }
153         void noCheatDigStart(const v3s16 &p)
154         {
155                 m_nocheat_dig_pos = p;
156                 m_nocheat_dig_time = 0;
157         }
158         v3s16 getNoCheatDigPos() { return m_nocheat_dig_pos; }
159         float getNoCheatDigTime() { return m_nocheat_dig_time; }
160         void noCheatDigEnd() { m_nocheat_dig_pos = v3s16(32767, 32767, 32767); }
161         LagPool &getDigPool() { return m_dig_pool; }
162         void setMaxSpeedOverride(const v3f &vel);
163         // Returns true if cheated
164         bool checkMovementCheat();
165
166         // Other
167
168         void updatePrivileges(const std::set<std::string> &privs, bool is_singleplayer)
169         {
170                 m_privs = privs;
171                 m_is_singleplayer = is_singleplayer;
172         }
173
174         bool getCollisionBox(aabb3f *toset) const override;
175         bool getSelectionBox(aabb3f *toset) const override;
176         bool collideWithObjects() const override { return true; }
177
178         void finalize(RemotePlayer *player, const std::set<std::string> &privs);
179
180         v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
181         v3f getEyeOffset() const;
182         float getZoomFOV() const;
183
184         inline Metadata &getMeta() { return m_meta; }
185
186 private:
187         std::string getPropertyPacket();
188         void unlinkPlayerSessionAndSave();
189         std::string generateUpdatePhysicsOverrideCommand() const;
190
191         RemotePlayer *m_player = nullptr;
192         session_t m_peer_id = 0;
193
194         // Cheat prevention
195         LagPool m_dig_pool;
196         LagPool m_move_pool;
197         v3f m_last_good_position;
198         float m_time_from_last_teleport = 0.0f;
199         float m_time_from_last_punch = 0.0f;
200         v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
201         float m_nocheat_dig_time = 0.0f;
202         float m_max_speed_override_time = 0.0f;
203         v3f m_max_speed_override = v3f(0.0f, 0.0f, 0.0f);
204
205         // Timers
206         IntervalLimiter m_breathing_interval;
207         IntervalLimiter m_drowning_interval;
208         IntervalLimiter m_node_hurt_interval;
209
210         bool m_position_not_sent = false;
211
212         // Cached privileges for enforcement
213         std::set<std::string> m_privs;
214         bool m_is_singleplayer;
215
216         u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
217         f32 m_pitch = 0.0f;
218         f32 m_fov = 0.0f;
219         s16 m_wanted_range = 0.0f;
220
221         Metadata m_meta;
222
223 public:
224         bool m_physics_override_sent = false;
225 };
226
227 struct PlayerHPChangeReason
228 {
229         enum Type : u8
230         {
231                 SET_HP,
232                 SET_HP_MAX, // internal type to allow distinguishing hp reset and damage (for effects)
233                 PLAYER_PUNCH,
234                 FALL,
235                 NODE_DAMAGE,
236                 DROWNING,
237                 RESPAWN
238         };
239
240         Type type = SET_HP;
241         bool from_mod = false;
242         int lua_reference = -1;
243
244         // For PLAYER_PUNCH
245         ServerActiveObject *object = nullptr;
246         // For NODE_DAMAGE
247         std::string node;
248
249         inline bool hasLuaReference() const { return lua_reference >= 0; }
250
251         bool setTypeFromString(const std::string &typestr)
252         {
253                 if (typestr == "set_hp")
254                         type = SET_HP;
255                 else if (typestr == "punch")
256                         type = PLAYER_PUNCH;
257                 else if (typestr == "fall")
258                         type = FALL;
259                 else if (typestr == "node_damage")
260                         type = NODE_DAMAGE;
261                 else if (typestr == "drown")
262                         type = DROWNING;
263                 else if (typestr == "respawn")
264                         type = RESPAWN;
265                 else
266                         return false;
267
268                 return true;
269         }
270
271         std::string getTypeAsString() const
272         {
273                 switch (type) {
274                 case PlayerHPChangeReason::SET_HP:
275                 case PlayerHPChangeReason::SET_HP_MAX:
276                         return "set_hp";
277                 case PlayerHPChangeReason::PLAYER_PUNCH:
278                         return "punch";
279                 case PlayerHPChangeReason::FALL:
280                         return "fall";
281                 case PlayerHPChangeReason::NODE_DAMAGE:
282                         return "node_damage";
283                 case PlayerHPChangeReason::DROWNING:
284                         return "drown";
285                 case PlayerHPChangeReason::RESPAWN:
286                         return "respawn";
287                 default:
288                         return "?";
289                 }
290         }
291
292         PlayerHPChangeReason(Type type) : type(type) {}
293
294         PlayerHPChangeReason(Type type, ServerActiveObject *object) :
295                         type(type), object(object)
296         {
297         }
298
299         PlayerHPChangeReason(Type type, std::string node) : type(type), node(node) {}
300 };