]> git.lizzy.rs Git - minetest.git/blob - src/serverenvironment.h
Environment & IGameDef code refactoring (#4985)
[minetest.git] / src / serverenvironment.h
1 /*
2 Minetest
3 Copyright (C) 2010-2017 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 SERVER_ENVIRONMENT_HEADER
21 #define SERVER_ENVIRONMENT_HEADER
22
23 #include "environment.h"
24
25 class IGameDef;
26 class ServerMap;
27 class RemotePlayer;
28 class PlayerSAO;
29 class ServerEnvironment;
30 class ActiveBlockModifier;
31 class ServerActiveObject;
32 class Server;
33 class GameScripting;
34
35 /*
36         {Active, Loading} block modifier interface.
37
38         These are fed into ServerEnvironment at initialization time;
39         ServerEnvironment handles deleting them.
40 */
41
42 class ActiveBlockModifier
43 {
44 public:
45         ActiveBlockModifier(){};
46         virtual ~ActiveBlockModifier(){};
47
48         // Set of contents to trigger on
49         virtual std::set<std::string> getTriggerContents()=0;
50         // Set of required neighbors (trigger doesn't happen if none are found)
51         // Empty = do not check neighbors
52         virtual std::set<std::string> getRequiredNeighbors()
53         { return std::set<std::string>(); }
54         // Trigger interval in seconds
55         virtual float getTriggerInterval() = 0;
56         // Random chance of (1 / return value), 0 is disallowed
57         virtual u32 getTriggerChance() = 0;
58         // Whether to modify chance to simulate time lost by an unnattended block
59         virtual bool getSimpleCatchUp() = 0;
60         // This is called usually at interval for 1/chance of the nodes
61         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
62         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
63                 u32 active_object_count, u32 active_object_count_wider){};
64 };
65
66 struct ABMWithState
67 {
68         ActiveBlockModifier *abm;
69         float timer;
70
71         ABMWithState(ActiveBlockModifier *abm_);
72 };
73
74 struct LoadingBlockModifierDef
75 {
76         // Set of contents to trigger on
77         std::set<std::string> trigger_contents;
78         std::string name;
79         bool run_at_every_load;
80
81         virtual ~LoadingBlockModifierDef() {}
82         virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n){};
83 };
84
85 struct LBMContentMapping
86 {
87         typedef std::map<content_t, std::vector<LoadingBlockModifierDef *> > container_map;
88         container_map map;
89
90         std::vector<LoadingBlockModifierDef *> lbm_list;
91
92         // Needs to be separate method (not inside destructor),
93         // because the LBMContentMapping may be copied and destructed
94         // many times during operation in the lbm_lookup_map.
95         void deleteContents();
96         void addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef);
97         const std::vector<LoadingBlockModifierDef *> *lookup(content_t c) const;
98 };
99
100 class LBMManager
101 {
102 public:
103         LBMManager():
104                 m_query_mode(false)
105         {}
106
107         ~LBMManager();
108
109         // Don't call this after loadIntroductionTimes() ran.
110         void addLBMDef(LoadingBlockModifierDef *lbm_def);
111
112         void loadIntroductionTimes(const std::string &times,
113                 IGameDef *gamedef, u32 now);
114
115         // Don't call this before loadIntroductionTimes() ran.
116         std::string createIntroductionTimesString();
117
118         // Don't call this before loadIntroductionTimes() ran.
119         void applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp);
120
121         // Warning: do not make this std::unordered_map, order is relevant here
122         typedef std::map<u32, LBMContentMapping> lbm_lookup_map;
123
124 private:
125         // Once we set this to true, we can only query,
126         // not modify
127         bool m_query_mode;
128
129         // For m_query_mode == false:
130         // The key of the map is the LBM def's name.
131         // TODO make this std::unordered_map
132         std::map<std::string, LoadingBlockModifierDef *> m_lbm_defs;
133
134         // For m_query_mode == true:
135         // The key of the map is the LBM def's first introduction time.
136         lbm_lookup_map m_lbm_lookup;
137
138         // Returns an iterator to the LBMs that were introduced
139         // after the given time. This is guaranteed to return
140         // valid values for everything
141         lbm_lookup_map::const_iterator getLBMsIntroducedAfter(u32 time)
142         { return m_lbm_lookup.lower_bound(time); }
143 };
144
145 /*
146         List of active blocks, used by ServerEnvironment
147 */
148
149 class ActiveBlockList
150 {
151 public:
152         void update(std::vector<v3s16> &active_positions,
153                 s16 radius,
154                 std::set<v3s16> &blocks_removed,
155                 std::set<v3s16> &blocks_added);
156
157         bool contains(v3s16 p){
158                 return (m_list.find(p) != m_list.end());
159         }
160
161         void clear(){
162                 m_list.clear();
163         }
164
165         std::set<v3s16> m_list;
166         std::set<v3s16> m_forceloaded_list;
167
168 private:
169 };
170
171 /*
172         Operation mode for ServerEnvironment::clearObjects()
173 */
174 enum ClearObjectsMode {
175         // Load and go through every mapblock, clearing objects
176                 CLEAR_OBJECTS_MODE_FULL,
177
178         // Clear objects immediately in loaded mapblocks;
179         // clear objects in unloaded mapblocks only when the mapblocks are next activated.
180                 CLEAR_OBJECTS_MODE_QUICK,
181 };
182
183 /*
184         The server-side environment.
185
186         This is not thread-safe. Server uses an environment mutex.
187 */
188
189 typedef UNORDERED_MAP<u16, ServerActiveObject *> ActiveObjectMap;
190
191 class ServerEnvironment : public Environment
192 {
193 public:
194         ServerEnvironment(ServerMap *map, GameScripting *scriptIface,
195                 Server *server, const std::string &path_world);
196         ~ServerEnvironment();
197
198         Map & getMap();
199
200         ServerMap & getServerMap();
201
202         //TODO find way to remove this fct!
203         GameScripting* getScriptIface()
204         { return m_script; }
205
206         Server *getGameDef()
207         { return m_server; }
208
209         float getSendRecommendedInterval()
210         { return m_recommended_send_interval; }
211
212         void kickAllPlayers(AccessDeniedCode reason,
213                 const std::string &str_reason, bool reconnect);
214         // Save players
215         void saveLoadedPlayers();
216         void savePlayer(RemotePlayer *player);
217         RemotePlayer *loadPlayer(const std::string &playername, PlayerSAO *sao);
218         void addPlayer(RemotePlayer *player);
219         void removePlayer(RemotePlayer *player);
220
221         /*
222                 Save and load time of day and game timer
223         */
224         void saveMeta();
225         void loadMeta();
226         // to be called instead of loadMeta if
227         // env_meta.txt doesn't exist (e.g. new world)
228         void loadDefaultMeta();
229
230         u32 addParticleSpawner(float exptime);
231         u32 addParticleSpawner(float exptime, u16 attached_id);
232         void deleteParticleSpawner(u32 id, bool remove_from_object = true);
233
234         /*
235                 External ActiveObject interface
236                 -------------------------------------------
237         */
238
239         ServerActiveObject* getActiveObject(u16 id);
240
241         /*
242                 Add an active object to the environment.
243                 Environment handles deletion of object.
244                 Object may be deleted by environment immediately.
245                 If id of object is 0, assigns a free id to it.
246                 Returns the id of the object.
247                 Returns 0 if not added and thus deleted.
248         */
249         u16 addActiveObject(ServerActiveObject *object);
250
251         /*
252                 Add an active object as a static object to the corresponding
253                 MapBlock.
254                 Caller allocates memory, ServerEnvironment frees memory.
255                 Return value: true if succeeded, false if failed.
256                 (note:  not used, pending removal from engine)
257         */
258         //bool addActiveObjectAsStatic(ServerActiveObject *object);
259
260         /*
261                 Find out what new objects have been added to
262                 inside a radius around a position
263         */
264         void getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
265                 s16 player_radius,
266                 std::set<u16> &current_objects,
267                 std::queue<u16> &added_objects);
268
269         /*
270                 Find out what new objects have been removed from
271                 inside a radius around a position
272         */
273         void getRemovedActiveObjects(PlayerSAO *playersao, s16 radius,
274                 s16 player_radius,
275                 std::set<u16> &current_objects,
276                 std::queue<u16> &removed_objects);
277
278         /*
279                 Get the next message emitted by some active object.
280                 Returns a message with id=0 if no messages are available.
281         */
282         ActiveObjectMessage getActiveObjectMessage();
283
284         /*
285                 Activate objects and dynamically modify for the dtime determined
286                 from timestamp and additional_dtime
287         */
288         void activateBlock(MapBlock *block, u32 additional_dtime=0);
289
290         /*
291                 {Active,Loading}BlockModifiers
292                 -------------------------------------------
293         */
294
295         void addActiveBlockModifier(ActiveBlockModifier *abm);
296         void addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm);
297
298         /*
299                 Other stuff
300                 -------------------------------------------
301         */
302
303         // Script-aware node setters
304         bool setNode(v3s16 p, const MapNode &n);
305         bool removeNode(v3s16 p);
306         bool swapNode(v3s16 p, const MapNode &n);
307
308         // Find all active objects inside a radius around a point
309         void getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius);
310
311         // Clear objects, loading and going through every MapBlock
312         void clearObjects(ClearObjectsMode mode);
313
314         // This makes stuff happen
315         void step(f32 dtime);
316
317         //check if there's a line of sight between two positions
318         bool line_of_sight(v3f pos1, v3f pos2, float stepsize=1.0, v3s16 *p=NULL);
319
320         u32 getGameTime() { return m_game_time; }
321
322         void reportMaxLagEstimate(float f) { m_max_lag_estimate = f; }
323         float getMaxLagEstimate() { return m_max_lag_estimate; }
324
325         std::set<v3s16>* getForceloadedBlocks() { return &m_active_blocks.m_forceloaded_list; };
326
327         // Sets the static object status all the active objects in the specified block
328         // This is only really needed for deleting blocks from the map
329         void setStaticForActiveObjectsInBlock(v3s16 blockpos,
330                 bool static_exists, v3s16 static_block=v3s16(0,0,0));
331
332         RemotePlayer *getPlayer(const u16 peer_id);
333         RemotePlayer *getPlayer(const char* name);
334 private:
335
336         /*
337                 Internal ActiveObject interface
338                 -------------------------------------------
339         */
340
341         /*
342                 Add an active object to the environment.
343
344                 Called by addActiveObject.
345
346                 Object may be deleted by environment immediately.
347                 If id of object is 0, assigns a free id to it.
348                 Returns the id of the object.
349                 Returns 0 if not added and thus deleted.
350         */
351         u16 addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s);
352
353         /*
354                 Remove all objects that satisfy (m_removed && m_known_by_count==0)
355         */
356         void removeRemovedObjects();
357
358         /*
359                 Convert stored objects from block to active
360         */
361         void activateObjects(MapBlock *block, u32 dtime_s);
362
363         /*
364                 Convert objects that are not in active blocks to static.
365
366                 If m_known_by_count != 0, active object is not deleted, but static
367                 data is still updated.
368
369                 If force_delete is set, active object is deleted nevertheless. It
370                 shall only be set so in the destructor of the environment.
371         */
372         void deactivateFarObjects(bool force_delete);
373
374         /*
375                 Member variables
376         */
377
378         // The map
379         ServerMap *m_map;
380         // Lua state
381         GameScripting* m_script;
382         // Server definition
383         Server *m_server;
384         // World path
385         const std::string m_path_world;
386         // Active object list
387         ActiveObjectMap m_active_objects;
388         // Outgoing network message buffer for active objects
389         std::queue<ActiveObjectMessage> m_active_object_messages;
390         // Some timers
391         float m_send_recommended_timer;
392         IntervalLimiter m_object_management_interval;
393         // List of active blocks
394         ActiveBlockList m_active_blocks;
395         IntervalLimiter m_active_blocks_management_interval;
396         IntervalLimiter m_active_block_modifier_interval;
397         IntervalLimiter m_active_blocks_nodemetadata_interval;
398         int m_active_block_interval_overload_skip;
399         // Time from the beginning of the game in seconds.
400         // Incremented in step().
401         u32 m_game_time;
402         // A helper variable for incrementing the latter
403         float m_game_time_fraction_counter;
404         // Time of last clearObjects call (game time).
405         // When a mapblock older than this is loaded, its objects are cleared.
406         u32 m_last_clear_objects_time;
407         // Active block modifiers
408         std::vector<ABMWithState> m_abms;
409         LBMManager m_lbm_mgr;
410         // An interval for generally sending object positions and stuff
411         float m_recommended_send_interval;
412         // Estimate for general maximum lag as determined by server.
413         // Can raise to high values like 15s with eg. map generation mods.
414         float m_max_lag_estimate;
415
416         // peer_ids in here should be unique, except that there may be many 0s
417         std::vector<RemotePlayer*> m_players;
418
419         // Particles
420         IntervalLimiter m_particle_management_interval;
421         UNORDERED_MAP<u32, float> m_particle_spawners;
422         UNORDERED_MAP<u32, u16> m_particle_spawner_attachments;
423 };
424
425 #endif