]> git.lizzy.rs Git - minetest.git/blob - src/server/player_sao.h
Dual wielding
[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 #include "util/pointedthing.h"
28
29 /*
30         PlayerSAO needs some internals exposed.
31 */
32
33 class LagPool
34 {
35         float m_pool = 15.0f;
36         float m_max = 15.0f;
37
38 public:
39         LagPool() = default;
40
41         void setMax(float new_max)
42         {
43                 m_max = new_max;
44                 if (m_pool > new_max)
45                         m_pool = new_max;
46         }
47
48         void add(float dtime)
49         {
50                 m_pool -= dtime;
51                 if (m_pool < 0)
52                         m_pool = 0;
53         }
54
55         void empty() { m_pool = m_max; }
56
57         bool grab(float dtime)
58         {
59                 if (dtime <= 0)
60                         return true;
61                 if (m_pool + dtime > m_max)
62                         return false;
63                 m_pool += dtime;
64                 return true;
65         }
66 };
67
68 class RemotePlayer;
69
70 class PlayerSAO : public UnitSAO
71 {
72 public:
73         PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_,
74                         bool is_singleplayer);
75
76         ActiveObjectType getType() const override { return ACTIVEOBJECT_TYPE_PLAYER; }
77         ActiveObjectType getSendType() const override { return ACTIVEOBJECT_TYPE_GENERIC; }
78         std::string getDescription() override;
79
80         /*
81                 Active object <-> environment interface
82         */
83
84         void addedToEnvironment(u32 dtime_s) override;
85         void removingFromEnvironment() override;
86         bool isStaticAllowed() const override { return false; }
87         bool shouldUnload() const override { return false; }
88         std::string getClientInitializationData(u16 protocol_version) override;
89         void getStaticData(std::string *result) const override;
90         void step(float dtime, bool send_recommended) override;
91         void setBasePosition(v3f position);
92         void setPos(const v3f &pos) override;
93         void moveTo(v3f pos, bool continuous) override;
94         void setPlayerYaw(const float yaw);
95         // Data should not be sent at player initialization
96         void setPlayerYawAndSend(const float yaw);
97         void setLookPitch(const float pitch);
98         // Data should not be sent at player initialization
99         void setLookPitchAndSend(const float pitch);
100         f32 getLookPitch() const { return m_pitch; }
101         f32 getRadLookPitch() const { return m_pitch * core::DEGTORAD; }
102         // Deprecated
103         f32 getRadLookPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; }
104         void setFov(const float pitch);
105         f32 getFov() const { return m_fov; }
106         void setWantedRange(const s16 range);
107         s16 getWantedRange() const { return m_wanted_range; }
108
109         /*
110                 Interaction interface
111         */
112
113         u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
114                         float time_from_last_punch, u16 initial_wear = 0) override;
115         void rightClick(ServerActiveObject *clicker) override;
116         void setHP(s32 hp, const PlayerHPChangeReason &reason) override
117         {
118                 return setHP(hp, reason, false);
119         }
120         void setHP(s32 hp, const PlayerHPChangeReason &reason, bool from_client);
121         void setHPRaw(u16 hp) { m_hp = hp; }
122         u16 getBreath() const { return m_breath; }
123         void setBreath(const u16 breath, bool send = true);
124
125         /*
126                 Inventory interface
127         */
128         Inventory *getInventory() const override;
129         InventoryLocation getInventoryLocation() const override;
130         void setInventoryModified() override {}
131         std::string getWieldList() const override { return "main"; }
132         u16 getWieldIndex() const override;
133         ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const override;
134         bool getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDefManager *itemdef_manager, PointedThing pointed) const;
135         bool setWieldedItem(const ItemStack &item) override;
136         bool setOffhandWieldedItem(const ItemStack &item);
137
138         /*
139                 PlayerSAO-specific
140         */
141
142         void disconnected();
143
144         RemotePlayer *getPlayer() { return m_player; }
145         session_t getPeerID() const { return m_peer_id; }
146
147         // Cheat prevention
148
149         v3f getLastGoodPosition() const { return m_last_good_position; }
150         float resetTimeFromLastPunch()
151         {
152                 float r = m_time_from_last_punch;
153                 m_time_from_last_punch = 0.0;
154                 return r;
155         }
156         void noCheatDigStart(const v3s16 &p)
157         {
158                 m_nocheat_dig_pos = p;
159                 m_nocheat_dig_time = 0;
160         }
161         v3s16 getNoCheatDigPos() { return m_nocheat_dig_pos; }
162         float getNoCheatDigTime() { return m_nocheat_dig_time; }
163         void noCheatDigEnd() { m_nocheat_dig_pos = v3s16(32767, 32767, 32767); }
164         LagPool &getDigPool() { return m_dig_pool; }
165         void setMaxSpeedOverride(const v3f &vel);
166         // Returns true if cheated
167         bool checkMovementCheat();
168
169         // Other
170
171         void updatePrivileges(const std::set<std::string> &privs, bool is_singleplayer)
172         {
173                 m_privs = privs;
174                 m_is_singleplayer = is_singleplayer;
175         }
176
177         bool getCollisionBox(aabb3f *toset) const override;
178         bool getSelectionBox(aabb3f *toset) const override;
179         bool collideWithObjects() const override { return true; }
180
181         void finalize(RemotePlayer *player, const std::set<std::string> &privs);
182
183         v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
184         v3f getEyeOffset() const;
185         float getZoomFOV() const;
186
187         inline SimpleMetadata &getMeta() { return m_meta; }
188
189 private:
190         std::string getPropertyPacket();
191         void unlinkPlayerSessionAndSave();
192         std::string generateUpdatePhysicsOverrideCommand() const;
193
194         RemotePlayer *m_player = nullptr;
195         session_t m_peer_id = 0;
196
197         // Cheat prevention
198         LagPool m_dig_pool;
199         LagPool m_move_pool;
200         v3f m_last_good_position;
201         float m_time_from_last_teleport = 0.0f;
202         float m_time_from_last_punch = 0.0f;
203         v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
204         float m_nocheat_dig_time = 0.0f;
205         float m_max_speed_override_time = 0.0f;
206         v3f m_max_speed_override = v3f(0.0f, 0.0f, 0.0f);
207
208         // Timers
209         IntervalLimiter m_breathing_interval;
210         IntervalLimiter m_drowning_interval;
211         IntervalLimiter m_node_hurt_interval;
212
213         bool m_position_not_sent = false;
214
215         // Cached privileges for enforcement
216         std::set<std::string> m_privs;
217         bool m_is_singleplayer;
218
219         u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
220         f32 m_pitch = 0.0f;
221         f32 m_fov = 0.0f;
222         s16 m_wanted_range = 0.0f;
223
224         SimpleMetadata m_meta;
225
226 public:
227         bool m_physics_override_sent = false;
228 };
229
230 struct PlayerHPChangeReason
231 {
232         enum Type : u8
233         {
234                 SET_HP,
235                 SET_HP_MAX, // internal type to allow distinguishing hp reset and damage (for effects)
236                 PLAYER_PUNCH,
237                 FALL,
238                 NODE_DAMAGE,
239                 DROWNING,
240                 RESPAWN
241         };
242
243         Type type = SET_HP;
244         bool from_mod = false;
245         int lua_reference = -1;
246
247         // For PLAYER_PUNCH
248         ServerActiveObject *object = nullptr;
249         // For NODE_DAMAGE
250         std::string node;
251
252         inline bool hasLuaReference() const { return lua_reference >= 0; }
253
254         bool setTypeFromString(const std::string &typestr)
255         {
256                 if (typestr == "set_hp")
257                         type = SET_HP;
258                 else if (typestr == "punch")
259                         type = PLAYER_PUNCH;
260                 else if (typestr == "fall")
261                         type = FALL;
262                 else if (typestr == "node_damage")
263                         type = NODE_DAMAGE;
264                 else if (typestr == "drown")
265                         type = DROWNING;
266                 else if (typestr == "respawn")
267                         type = RESPAWN;
268                 else
269                         return false;
270
271                 return true;
272         }
273
274         std::string getTypeAsString() const
275         {
276                 switch (type) {
277                 case PlayerHPChangeReason::SET_HP:
278                 case PlayerHPChangeReason::SET_HP_MAX:
279                         return "set_hp";
280                 case PlayerHPChangeReason::PLAYER_PUNCH:
281                         return "punch";
282                 case PlayerHPChangeReason::FALL:
283                         return "fall";
284                 case PlayerHPChangeReason::NODE_DAMAGE:
285                         return "node_damage";
286                 case PlayerHPChangeReason::DROWNING:
287                         return "drown";
288                 case PlayerHPChangeReason::RESPAWN:
289                         return "respawn";
290                 default:
291                         return "?";
292                 }
293         }
294
295         PlayerHPChangeReason(Type type) : type(type) {}
296
297         PlayerHPChangeReason(Type type, ServerActiveObject *object) :
298                         type(type), object(object)
299         {
300         }
301
302         PlayerHPChangeReason(Type type, std::string node) : type(type), node(node) {}
303 };