Fix --color command line parameter ignorance (#7173)
[oweals/minetest.git] / src / content_sao.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #pragma once
21
22 #include "network/networkprotocol.h"
23 #include "util/numeric.h"
24 #include "serverobject.h"
25 #include "itemgroup.h"
26 #include "object_properties.h"
27 #include "constants.h"
28
29 class UnitSAO: public ServerActiveObject
30 {
31 public:
32         UnitSAO(ServerEnvironment *env, v3f pos);
33         virtual ~UnitSAO() = default;
34
35         void setRotation(v3f rotation) { m_rotation = rotation; }
36         const v3f &getRotation() const { return m_rotation; }
37         v3f getRadRotation() { return m_rotation * core::DEGTORAD; }
38
39         // Deprecated
40         f32 getRadYawDep() const { return (m_rotation.Y + 90.) * core::DEGTORAD; }
41
42         u16 getHP() const { return m_hp; }
43         // Use a function, if isDead can be defined by other conditions
44         bool isDead() const { return m_hp == 0; }
45
46         inline bool isAttached() const
47         { return getParent(); }
48
49         void setArmorGroups(const ItemGroupList &armor_groups);
50         const ItemGroupList &getArmorGroups();
51         void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop);
52         void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop);
53         void setAnimationSpeed(float frame_speed);
54         void setBonePosition(const std::string &bone, v3f position, v3f rotation);
55         void getBonePosition(const std::string &bone, v3f *position, v3f *rotation);
56         void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation);
57         void getAttachment(int *parent_id, std::string *bone, v3f *position, v3f *rotation);
58         void clearChildAttachments();
59         void clearParentAttachment();
60         void addAttachmentChild(int child_id);
61         void removeAttachmentChild(int child_id);
62         const std::unordered_set<int> &getAttachmentChildIds();
63         ServerActiveObject *getParent() const;
64         ObjectProperties* accessObjectProperties();
65         void notifyObjectPropertiesModified();
66 protected:
67         u16 m_hp = 1;
68
69         v3f m_rotation;
70
71         bool m_properties_sent = true;
72         ObjectProperties m_prop;
73
74         ItemGroupList m_armor_groups;
75         bool m_armor_groups_sent = false;
76
77         v2f m_animation_range;
78         float m_animation_speed = 0.0f;
79         float m_animation_blend = 0.0f;
80         bool m_animation_loop = true;
81         bool m_animation_sent = false;
82         bool m_animation_speed_sent = false;
83
84         // Stores position and rotation for each bone name
85         std::unordered_map<std::string, core::vector2d<v3f>> m_bone_position;
86         bool m_bone_position_sent = false;
87
88         int m_attachment_parent_id = 0;
89         std::unordered_set<int> m_attachment_child_ids;
90         std::string m_attachment_bone = "";
91         v3f m_attachment_position;
92         v3f m_attachment_rotation;
93         bool m_attachment_sent = false;
94 private:
95         void onAttach(int parent_id);
96         void onDetach(int parent_id);
97 };
98
99 /*
100         LuaEntitySAO needs some internals exposed.
101 */
102
103 class LuaEntitySAO : public UnitSAO
104 {
105 public:
106         LuaEntitySAO(ServerEnvironment *env, v3f pos,
107                      const std::string &name, const std::string &state);
108         ~LuaEntitySAO();
109         ActiveObjectType getType() const
110         { return ACTIVEOBJECT_TYPE_LUAENTITY; }
111         ActiveObjectType getSendType() const
112         { return ACTIVEOBJECT_TYPE_GENERIC; }
113         virtual void addedToEnvironment(u32 dtime_s);
114         static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
115                         const std::string &data);
116         void step(float dtime, bool send_recommended);
117         std::string getClientInitializationData(u16 protocol_version);
118         bool isStaticAllowed() const
119         { return m_prop.static_save; }
120         void getStaticData(std::string *result) const;
121         int punch(v3f dir,
122                         const ToolCapabilities *toolcap=NULL,
123                         ServerActiveObject *puncher=NULL,
124                         float time_from_last_punch=1000000);
125         void rightClick(ServerActiveObject *clicker);
126         void setPos(const v3f &pos);
127         void moveTo(v3f pos, bool continuous);
128         float getMinimumSavedMovement();
129         std::string getDescription();
130         void setHP(s32 hp, const PlayerHPChangeReason &reason);
131         u16 getHP() const;
132         /* LuaEntitySAO-specific */
133         void setVelocity(v3f velocity);
134         void addVelocity(v3f velocity)
135         {
136                 m_velocity += velocity;
137         }
138         v3f getVelocity();
139         void setAcceleration(v3f acceleration);
140         v3f getAcceleration();
141
142         void setTextureMod(const std::string &mod);
143         std::string getTextureMod() const;
144         void setSprite(v2s16 p, int num_frames, float framelength,
145                         bool select_horiz_by_yawpitch);
146         std::string getName();
147         bool getCollisionBox(aabb3f *toset) const;
148         bool getSelectionBox(aabb3f *toset) const;
149         bool collideWithObjects() const;
150 private:
151         std::string getPropertyPacket();
152         void sendPosition(bool do_interpolate, bool is_movement_end);
153
154         std::string m_init_name;
155         std::string m_init_state;
156         bool m_registered = false;
157
158         v3f m_velocity;
159         v3f m_acceleration;
160
161         v3f m_last_sent_position;
162         v3f m_last_sent_velocity;
163         v3f m_last_sent_rotation;
164         float m_last_sent_position_timer = 0.0f;
165         float m_last_sent_move_precision = 0.0f;
166         std::string m_current_texture_modifier = "";
167 };
168
169 /*
170         PlayerSAO needs some internals exposed.
171 */
172
173 class LagPool
174 {
175         float m_pool = 15.0f;
176         float m_max = 15.0f;
177 public:
178         LagPool() = default;
179
180         void setMax(float new_max)
181         {
182                 m_max = new_max;
183                 if(m_pool > new_max)
184                         m_pool = new_max;
185         }
186
187         void add(float dtime)
188         {
189                 m_pool -= dtime;
190                 if(m_pool < 0)
191                         m_pool = 0;
192         }
193
194         void empty()
195         {
196                 m_pool = m_max;
197         }
198
199         bool grab(float dtime)
200         {
201                 if(dtime <= 0)
202                         return true;
203                 if(m_pool + dtime > m_max)
204                         return false;
205                 m_pool += dtime;
206                 return true;
207         }
208 };
209
210 class RemotePlayer;
211
212 class PlayerSAO : public UnitSAO
213 {
214 public:
215         PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_,
216                         bool is_singleplayer);
217         ~PlayerSAO();
218         ActiveObjectType getType() const
219         { return ACTIVEOBJECT_TYPE_PLAYER; }
220         ActiveObjectType getSendType() const
221         { return ACTIVEOBJECT_TYPE_GENERIC; }
222         std::string getDescription();
223
224         /*
225                 Active object <-> environment interface
226         */
227
228         void addedToEnvironment(u32 dtime_s);
229         void removingFromEnvironment();
230         bool isStaticAllowed() const { return false; }
231         std::string getClientInitializationData(u16 protocol_version);
232         void getStaticData(std::string *result) const;
233         void step(float dtime, bool send_recommended);
234         void setBasePosition(const v3f &position);
235         void setPos(const v3f &pos);
236         void moveTo(v3f pos, bool continuous);
237         void setPlayerYaw(const float yaw);
238         // Data should not be sent at player initialization
239         void setPlayerYawAndSend(const float yaw);
240         void setLookPitch(const float pitch);
241         // Data should not be sent at player initialization
242         void setLookPitchAndSend(const float pitch);
243         f32 getLookPitch() const { return m_pitch; }
244         f32 getRadLookPitch() const { return m_pitch * core::DEGTORAD; }
245         // Deprecated
246         f32 getRadLookPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; }
247         void setFov(const float pitch);
248         f32 getFov() const { return m_fov; }
249         void setWantedRange(const s16 range);
250         s16 getWantedRange() const { return m_wanted_range; }
251
252         /*
253                 Interaction interface
254         */
255
256         int punch(v3f dir,
257                 const ToolCapabilities *toolcap,
258                 ServerActiveObject *puncher,
259                 float time_from_last_punch);
260         void rightClick(ServerActiveObject *clicker) {}
261         void setHP(s32 hp, const PlayerHPChangeReason &reason);
262         void setHPRaw(u16 hp) { m_hp = hp; }
263         s16 readDamage();
264         u16 getBreath() const { return m_breath; }
265         void setBreath(const u16 breath, bool send = true);
266
267         /*
268                 Inventory interface
269         */
270
271         Inventory* getInventory();
272         const Inventory* getInventory() const;
273         InventoryLocation getInventoryLocation() const;
274         std::string getWieldList() const;
275         ItemStack getWieldedItem() const;
276         ItemStack getWieldedItemOrHand() const;
277         bool setWieldedItem(const ItemStack &item);
278         int getWieldIndex() const;
279         void setWieldIndex(int i);
280
281         /*
282                 PlayerSAO-specific
283         */
284
285         void disconnected();
286
287         RemotePlayer *getPlayer() { return m_player; }
288         session_t getPeerID() const { return m_peer_id; }
289
290         // Cheat prevention
291
292         v3f getLastGoodPosition() const
293         {
294                 return m_last_good_position;
295         }
296         float resetTimeFromLastPunch()
297         {
298                 float r = m_time_from_last_punch;
299                 m_time_from_last_punch = 0.0;
300                 return r;
301         }
302         void noCheatDigStart(const v3s16 &p)
303         {
304                 m_nocheat_dig_pos = p;
305                 m_nocheat_dig_time = 0;
306         }
307         v3s16 getNoCheatDigPos()
308         {
309                 return m_nocheat_dig_pos;
310         }
311         float getNoCheatDigTime()
312         {
313                 return m_nocheat_dig_time;
314         }
315         void noCheatDigEnd()
316         {
317                 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
318         }
319         LagPool& getDigPool()
320         {
321                 return m_dig_pool;
322         }
323         // Returns true if cheated
324         bool checkMovementCheat();
325
326         // Other
327
328         void updatePrivileges(const std::set<std::string> &privs,
329                         bool is_singleplayer)
330         {
331                 m_privs = privs;
332                 m_is_singleplayer = is_singleplayer;
333         }
334
335         bool getCollisionBox(aabb3f *toset) const;
336         bool getSelectionBox(aabb3f *toset) const;
337         bool collideWithObjects() const { return true; }
338
339         void finalize(RemotePlayer *player, const std::set<std::string> &privs);
340
341         v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
342         v3f getEyeOffset() const;
343         float getZoomFOV() const;
344
345         inline Metadata &getMeta() { return m_meta; }
346
347 private:
348         std::string getPropertyPacket();
349         void unlinkPlayerSessionAndSave();
350
351         RemotePlayer *m_player = nullptr;
352         session_t m_peer_id = 0;
353         Inventory *m_inventory = nullptr;
354
355         // Cheat prevention
356         LagPool m_dig_pool;
357         LagPool m_move_pool;
358         v3f m_last_good_position;
359         float m_time_from_last_teleport = 0.0f;
360         float m_time_from_last_punch = 0.0f;
361         v3s16 m_nocheat_dig_pos = v3s16(32767, 32767, 32767);
362         float m_nocheat_dig_time = 0.0f;
363
364         // Timers
365         IntervalLimiter m_breathing_interval;
366         IntervalLimiter m_drowning_interval;
367         IntervalLimiter m_node_hurt_interval;
368
369         int m_wield_index = 0;
370         bool m_position_not_sent = false;
371
372         // Cached privileges for enforcement
373         std::set<std::string> m_privs;
374         bool m_is_singleplayer;
375
376         u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
377         f32 m_pitch = 0.0f;
378         f32 m_fov = 0.0f;
379         s16 m_wanted_range = 0.0f;
380
381         Metadata m_meta;
382 public:
383         float m_physics_override_speed = 1.0f;
384         float m_physics_override_jump = 1.0f;
385         float m_physics_override_gravity = 1.0f;
386         bool m_physics_override_sneak = true;
387         bool m_physics_override_sneak_glitch = false;
388         bool m_physics_override_new_move = true;
389         bool m_physics_override_sent = false;
390 };
391
392
393 struct PlayerHPChangeReason {
394         enum Type : u8 {
395                 SET_HP,
396                 PLAYER_PUNCH,
397                 FALL,
398                 NODE_DAMAGE,
399                 DROWNING,
400                 RESPAWN
401         };
402
403         Type type = SET_HP;
404         ServerActiveObject *object;
405         bool from_mod = false;
406         int lua_reference = -1;
407
408         bool setTypeFromString(const std::string &typestr)
409         {
410                 if (typestr == "set_hp")
411                         type = SET_HP;
412                 else if (typestr == "punch")
413                         type = PLAYER_PUNCH;
414                 else if (typestr == "fall")
415                         type = FALL;
416                 else if (typestr == "node_damage")
417                         type = NODE_DAMAGE;
418                 else if (typestr == "drown")
419                         type = DROWNING;
420                 else if (typestr == "respawn")
421                         type = RESPAWN;
422                 else
423                         return false;
424
425                 return true;
426         }
427
428         std::string getTypeAsString() const
429         {
430                 switch (type) {
431                 case PlayerHPChangeReason::SET_HP:
432                         return "set_hp";
433                 case PlayerHPChangeReason::PLAYER_PUNCH:
434                         return "punch";
435                 case PlayerHPChangeReason::FALL:
436                         return "fall";
437                 case PlayerHPChangeReason::NODE_DAMAGE:
438                         return "node_damage";
439                 case PlayerHPChangeReason::DROWNING:
440                         return "drown";
441                 case PlayerHPChangeReason::RESPAWN:
442                         return "respawn";
443                 default:
444                         return "?";
445                 }
446         }
447
448         PlayerHPChangeReason(Type type, ServerActiveObject *object=NULL):
449                         type(type), object(object)
450         {}
451 };