Fix race condition on accessing m_time_of_day_speed causing day night race on some...
[oweals/minetest.git] / src / environment.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 #ifndef ENVIRONMENT_HEADER
21 #define ENVIRONMENT_HEADER
22
23 /*
24         This class is the game's environment.
25         It contains:
26         - The map
27         - Players
28         - Other objects
29         - The current time in the game
30         - etc.
31 */
32
33 #include <set>
34 #include <list>
35 #include <map>
36 #include "irr_v3d.h"
37 #include "activeobject.h"
38 #include "util/numeric.h"
39 #include "mapnode.h"
40 #include "mapblock.h"
41 #include "jthread/jmutex.h"
42
43 class ServerEnvironment;
44 class ActiveBlockModifier;
45 class ServerActiveObject;
46 class ITextureSource;
47 class IGameDef;
48 class Map;
49 class ServerMap;
50 class ClientMap;
51 class GameScripting;
52 class Player;
53
54 class Environment
55 {
56 public:
57         // Environment will delete the map passed to the constructor
58         Environment();
59         virtual ~Environment();
60
61         /*
62                 Step everything in environment.
63                 - Move players
64                 - Step mobs
65                 - Run timers of map
66         */
67         virtual void step(f32 dtime) = 0;
68
69         virtual Map & getMap() = 0;
70
71         virtual void addPlayer(Player *player);
72         void removePlayer(u16 peer_id);
73         Player * getPlayer(u16 peer_id);
74         Player * getPlayer(const char *name);
75         Player * getRandomConnectedPlayer();
76         Player * getNearestConnectedPlayer(v3f pos);
77         std::list<Player*> getPlayers();
78         std::list<Player*> getPlayers(bool ignore_disconnected);
79         
80         u32 getDayNightRatio();
81
82         // 0-23999
83         virtual void setTimeOfDay(u32 time)
84         {
85                 m_time_of_day = time;
86                 m_time_of_day_f = (float)time / 24000.0;
87         }
88
89         u32 getTimeOfDay()
90         { return m_time_of_day; }
91
92         float getTimeOfDayF()
93         { return m_time_of_day_f; }
94
95         void stepTimeOfDay(float dtime);
96
97         void setTimeOfDaySpeed(float speed);
98         
99         float getTimeOfDaySpeed();
100
101         void setDayNightRatioOverride(bool enable, u32 value)
102         {
103                 m_enable_day_night_ratio_override = enable;
104                 m_day_night_ratio_override = value;
105         }
106
107         // counter used internally when triggering ABMs
108         u32 m_added_objects;
109
110 protected:
111         // peer_ids in here should be unique, except that there may be many 0s
112         std::list<Player*> m_players;
113         // Time of day in milli-hours (0-23999); determines day and night
114         u32 m_time_of_day;
115         // Time of day in 0...1
116         float m_time_of_day_f;
117         float m_time_of_day_speed;
118         // Used to buffer dtime for adding to m_time_of_day
119         float m_time_counter;
120         // Overriding the day-night ratio is useful for custom sky visuals
121         bool m_enable_day_night_ratio_override;
122         u32 m_day_night_ratio_override;
123         
124 private:
125         JMutex m_lock;
126
127 };
128
129 /*
130         Active block modifier interface.
131
132         These are fed into ServerEnvironment at initialization time;
133         ServerEnvironment handles deleting them.
134 */
135
136 class ActiveBlockModifier
137 {
138 public:
139         ActiveBlockModifier(){};
140         virtual ~ActiveBlockModifier(){};
141         
142         // Set of contents to trigger on
143         virtual std::set<std::string> getTriggerContents()=0;
144         // Set of required neighbors (trigger doesn't happen if none are found)
145         // Empty = do not check neighbors
146         virtual std::set<std::string> getRequiredNeighbors()
147         { return std::set<std::string>(); }
148         // Trigger interval in seconds
149         virtual float getTriggerInterval() = 0;
150         // Random chance of (1 / return value), 0 is disallowed
151         virtual u32 getTriggerChance() = 0;
152         // This is called usually at interval for 1/chance of the nodes
153         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
154         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
155                         u32 active_object_count, u32 active_object_count_wider){};
156 };
157
158 struct ABMWithState
159 {
160         ActiveBlockModifier *abm;
161         float timer;
162
163         ABMWithState(ActiveBlockModifier *abm_);
164 };
165
166 /*
167         List of active blocks, used by ServerEnvironment
168 */
169
170 class ActiveBlockList
171 {
172 public:
173         void update(std::list<v3s16> &active_positions,
174                         s16 radius,
175                         std::set<v3s16> &blocks_removed,
176                         std::set<v3s16> &blocks_added);
177
178         bool contains(v3s16 p){
179                 return (m_list.find(p) != m_list.end());
180         }
181
182         void clear(){
183                 m_list.clear();
184         }
185
186         std::set<v3s16> m_list;
187         std::set<v3s16> m_forceloaded_list;
188
189 private:
190 };
191
192 /*
193         The server-side environment.
194
195         This is not thread-safe. Server uses an environment mutex.
196 */
197
198 class ServerEnvironment : public Environment
199 {
200 public:
201         ServerEnvironment(ServerMap *map, GameScripting *scriptIface,
202                         IGameDef *gamedef);
203         ~ServerEnvironment();
204
205         Map & getMap();
206
207         ServerMap & getServerMap();
208
209         //TODO find way to remove this fct!
210         GameScripting* getScriptIface()
211                 { return m_script; }
212
213         IGameDef *getGameDef()
214                 { return m_gamedef; }
215
216         float getSendRecommendedInterval()
217                 { return m_recommended_send_interval; }
218
219         /*
220                 Save players
221         */
222         void serializePlayers(const std::string &savedir);
223         void deSerializePlayers(const std::string &savedir);
224
225         /*
226                 Save and load time of day and game timer
227         */
228         void saveMeta(const std::string &savedir);
229         void loadMeta(const std::string &savedir);
230
231         /*
232                 External ActiveObject interface
233                 -------------------------------------------
234         */
235
236         ServerActiveObject* getActiveObject(u16 id);
237
238         /*
239                 Add an active object to the environment.
240                 Environment handles deletion of object.
241                 Object may be deleted by environment immediately.
242                 If id of object is 0, assigns a free id to it.
243                 Returns the id of the object.
244                 Returns 0 if not added and thus deleted.
245         */
246         u16 addActiveObject(ServerActiveObject *object);
247         
248         /*
249                 Add an active object as a static object to the corresponding
250                 MapBlock.
251                 Caller allocates memory, ServerEnvironment frees memory.
252                 Return value: true if succeeded, false if failed.
253                 (note:  not used, pending removal from engine)
254         */
255         //bool addActiveObjectAsStatic(ServerActiveObject *object);
256         
257         /*
258                 Find out what new objects have been added to
259                 inside a radius around a position
260         */
261         void getAddedActiveObjects(v3s16 pos, s16 radius,
262                         std::set<u16> &current_objects,
263                         std::set<u16> &added_objects);
264
265         /*
266                 Find out what new objects have been removed from
267                 inside a radius around a position
268         */
269         void getRemovedActiveObjects(v3s16 pos, s16 radius,
270                         std::set<u16> &current_objects,
271                         std::set<u16> &removed_objects);
272         
273         /*
274                 Get the next message emitted by some active object.
275                 Returns a message with id=0 if no messages are available.
276         */
277         ActiveObjectMessage getActiveObjectMessage();
278
279         /*
280                 Activate objects and dynamically modify for the dtime determined
281                 from timestamp and additional_dtime
282         */
283         void activateBlock(MapBlock *block, u32 additional_dtime=0);
284
285         /*
286                 ActiveBlockModifiers
287                 -------------------------------------------
288         */
289
290         void addActiveBlockModifier(ActiveBlockModifier *abm);
291
292         /*
293                 Other stuff
294                 -------------------------------------------
295         */
296
297         // Script-aware node setters
298         bool setNode(v3s16 p, const MapNode &n);
299         bool removeNode(v3s16 p);
300         bool swapNode(v3s16 p, const MapNode &n);
301         
302         // Find all active objects inside a radius around a point
303         std::set<u16> getObjectsInsideRadius(v3f pos, float radius);
304         
305         // Clear all objects, loading and going through every MapBlock
306         void clearAllObjects();
307         
308         // This makes stuff happen
309         void step(f32 dtime);
310         
311         //check if there's a line of sight between two positions
312         bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0, v3s16 *p=NULL);
313
314         u32 getGameTime() { return m_game_time; }
315
316         void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
317         float getMaxLagEstimate() { return m_max_lag_estimate; }
318         
319         std::set<v3s16>* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; };
320         
321 private:
322
323         /*
324                 Internal ActiveObject interface
325                 -------------------------------------------
326         */
327
328         /*
329                 Add an active object to the environment.
330
331                 Called by addActiveObject.
332
333                 Object may be deleted by environment immediately.
334                 If id of object is 0, assigns a free id to it.
335                 Returns the id of the object.
336                 Returns 0 if not added and thus deleted.
337         */
338         u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s);
339         
340         /*
341                 Remove all objects that satisfy (m_removed && m_known_by_count==0)
342         */
343         void removeRemovedObjects();
344         
345         /*
346                 Convert stored objects from block to active
347         */
348         void activateObjects(MapBlock *block, u32 dtime_s);
349         
350         /*
351                 Convert objects that are not in active blocks to static.
352
353                 If m_known_by_count != 0, active object is not deleted, but static
354                 data is still updated.
355
356                 If force_delete is set, active object is deleted nevertheless. It
357                 shall only be set so in the destructor of the environment.
358         */
359         void deactivateFarObjects(bool force_delete);
360
361         /*
362                 Member variables
363         */
364         
365         // The map
366         ServerMap *m_map;
367         // Lua state
368         GameScripting* m_script;
369         // Game definition
370         IGameDef *m_gamedef;
371         // Active object list
372         std::map<u16, ServerActiveObject*> m_active_objects;
373         // Outgoing network message buffer for active objects
374         std::list<ActiveObjectMessage> m_active_object_messages;
375         // Some timers
376         float m_send_recommended_timer;
377         IntervalLimiter m_object_management_interval;
378         // List of active blocks
379         ActiveBlockList m_active_blocks;
380         IntervalLimiter m_active_blocks_management_interval;
381         IntervalLimiter m_active_block_modifier_interval;
382         IntervalLimiter m_active_blocks_nodemetadata_interval;
383         int m_active_block_interval_overload_skip;
384         // Time from the beginning of the game in seconds.
385         // Incremented in step().
386         u32 m_game_time;
387         // A helper variable for incrementing the latter
388         float m_game_time_fraction_counter;
389         std::list<ABMWithState> m_abms;
390         // An interval for generally sending object positions and stuff
391         float m_recommended_send_interval;
392         // Estimate for general maximum lag as determined by server.
393         // Can raise to high values like 15s with eg. map generation mods.
394         float m_max_lag_estimate;
395 };
396
397 #ifndef SERVER
398
399 #include "clientobject.h"
400 class ClientSimpleObject;
401
402 /*
403         The client-side environment.
404
405         This is not thread-safe.
406         Must be called from main (irrlicht) thread (uses the SceneManager)
407         Client uses an environment mutex.
408 */
409
410 enum ClientEnvEventType
411 {
412         CEE_NONE,
413         CEE_PLAYER_DAMAGE,
414         CEE_PLAYER_BREATH
415 };
416
417 struct ClientEnvEvent
418 {
419         ClientEnvEventType type;
420         union {
421                 struct{
422                 } none;
423                 struct{
424                         u8 amount;
425                         bool send_to_server;
426                 } player_damage;
427                 struct{
428                         u16 amount;
429                 } player_breath;
430         };
431 };
432
433 class ClientEnvironment : public Environment
434 {
435 public:
436         ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
437                         ITextureSource *texturesource, IGameDef *gamedef,
438                         IrrlichtDevice *device);
439         ~ClientEnvironment();
440
441         Map & getMap();
442         ClientMap & getClientMap();
443
444         IGameDef *getGameDef()
445         { return m_gamedef; }
446
447         void step(f32 dtime);
448
449         virtual void addPlayer(Player *player);
450         LocalPlayer * getLocalPlayer();
451         
452         /*
453                 ClientSimpleObjects
454         */
455
456         void addSimpleObject(ClientSimpleObject *simple);
457
458         /*
459                 ActiveObjects
460         */
461         
462         ClientActiveObject* getActiveObject(u16 id);
463
464         /*
465                 Adds an active object to the environment.
466                 Environment handles deletion of object.
467                 Object may be deleted by environment immediately.
468                 If id of object is 0, assigns a free id to it.
469                 Returns the id of the object.
470                 Returns 0 if not added and thus deleted.
471         */
472         u16 addActiveObject(ClientActiveObject *object);
473
474         void addActiveObject(u16 id, u8 type, const std::string &init_data);
475         void removeActiveObject(u16 id);
476
477         void processActiveObjectMessage(u16 id, const std::string &data);
478
479         /*
480                 Callbacks for activeobjects
481         */
482
483         void damageLocalPlayer(u8 damage, bool handle_hp=true);
484         void updateLocalPlayerBreath(u16 breath);
485
486         /*
487                 Client likes to call these
488         */
489         
490         // Get all nearby objects
491         void getActiveObjects(v3f origin, f32 max_d,
492                         std::vector<DistanceSortedActiveObject> &dest);
493         
494         // Get event from queue. CEE_NONE is returned if queue is empty.
495         ClientEnvEvent getClientEvent();
496
497         u16 m_attachements[USHRT_MAX];
498
499         std::list<std::string> getPlayerNames()
500         { return m_player_names; }
501         void addPlayerName(std::string name)
502         { m_player_names.push_back(name); }
503         void removePlayerName(std::string name)
504         { m_player_names.remove(name); }
505         void updateCameraOffset(v3s16 camera_offset)
506         { m_camera_offset = camera_offset; }
507         v3s16 getCameraOffset()
508         { return m_camera_offset; }
509         
510 private:
511         ClientMap *m_map;
512         scene::ISceneManager *m_smgr;
513         ITextureSource *m_texturesource;
514         IGameDef *m_gamedef;
515         IrrlichtDevice *m_irr;
516         std::map<u16, ClientActiveObject*> m_active_objects;
517         std::list<ClientSimpleObject*> m_simple_objects;
518         std::list<ClientEnvEvent> m_client_event_queue;
519         IntervalLimiter m_active_object_light_update_interval;
520         IntervalLimiter m_lava_hurt_interval;
521         IntervalLimiter m_drowning_interval;
522         IntervalLimiter m_breathing_interval;
523         std::list<std::string> m_player_names;
524         v3s16 m_camera_offset;
525 };
526
527 #endif
528
529 #endif
530