Modernize various files (src/m*) (#6267)
[oweals/minetest.git] / src / map.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 <iostream>
23 #include <sstream>
24 #include <set>
25 #include <map>
26 #include <list>
27
28 #include "irrlichttypes_bloated.h"
29 #include "mapnode.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "modifiedstate.h"
33 #include "util/container.h"
34 #include "nodetimer.h"
35 #include "map_settings_manager.h"
36
37 class Settings;
38 class MapDatabase;
39 class ClientMap;
40 class MapSector;
41 class ServerMapSector;
42 class MapBlock;
43 class NodeMetadata;
44 class IGameDef;
45 class IRollbackManager;
46 class EmergeManager;
47 class ServerEnvironment;
48 struct BlockMakeData;
49
50 /*
51         MapEditEvent
52 */
53
54 #define MAPTYPE_BASE 0
55 #define MAPTYPE_SERVER 1
56 #define MAPTYPE_CLIENT 2
57
58 enum MapEditEventType{
59         // Node added (changed from air or something else to something)
60         MEET_ADDNODE,
61         // Node removed (changed to air)
62         MEET_REMOVENODE,
63         // Node swapped (changed without metadata change)
64         MEET_SWAPNODE,
65         // Node metadata of block changed (not knowing which node exactly)
66         // p stores block coordinate
67         MEET_BLOCK_NODE_METADATA_CHANGED,
68         // Anything else (modified_blocks are set unsent)
69         MEET_OTHER
70 };
71
72 struct MapEditEvent
73 {
74         MapEditEventType type = MEET_OTHER;
75         v3s16 p;
76         MapNode n = CONTENT_AIR;
77         std::set<v3s16> modified_blocks;
78         u16 already_known_by_peer = 0;
79
80         MapEditEvent() = default;
81
82         MapEditEvent * clone()
83         {
84                 MapEditEvent *event = new MapEditEvent();
85                 event->type = type;
86                 event->p = p;
87                 event->n = n;
88                 event->modified_blocks = modified_blocks;
89                 return event;
90         }
91
92         VoxelArea getArea()
93         {
94                 switch(type){
95                 case MEET_ADDNODE:
96                         return VoxelArea(p);
97                 case MEET_REMOVENODE:
98                         return VoxelArea(p);
99                 case MEET_SWAPNODE:
100                         return VoxelArea(p);
101                 case MEET_BLOCK_NODE_METADATA_CHANGED:
102                 {
103                         v3s16 np1 = p*MAP_BLOCKSIZE;
104                         v3s16 np2 = np1 + v3s16(1,1,1)*MAP_BLOCKSIZE - v3s16(1,1,1);
105                         return VoxelArea(np1, np2);
106                 }
107                 case MEET_OTHER:
108                 {
109                         VoxelArea a;
110                         for (v3s16 p : modified_blocks) {
111                                 v3s16 np1 = p*MAP_BLOCKSIZE;
112                                 v3s16 np2 = np1 + v3s16(1,1,1)*MAP_BLOCKSIZE - v3s16(1,1,1);
113                                 a.addPoint(np1);
114                                 a.addPoint(np2);
115                         }
116                         return a;
117                 }
118                 }
119                 return VoxelArea();
120         }
121 };
122
123 class MapEventReceiver
124 {
125 public:
126         // event shall be deleted by caller after the call.
127         virtual void onMapEditEvent(MapEditEvent *event) = 0;
128 };
129
130 class Map /*: public NodeContainer*/
131 {
132 public:
133
134         Map(std::ostream &dout, IGameDef *gamedef);
135         virtual ~Map();
136         DISABLE_CLASS_COPY(Map);
137
138         virtual s32 mapType() const
139         {
140                 return MAPTYPE_BASE;
141         }
142
143         /*
144                 Drop (client) or delete (server) the map.
145         */
146         virtual void drop()
147         {
148                 delete this;
149         }
150
151         void addEventReceiver(MapEventReceiver *event_receiver);
152         void removeEventReceiver(MapEventReceiver *event_receiver);
153         // event shall be deleted by caller after the call.
154         void dispatchEvent(MapEditEvent *event);
155
156         // On failure returns NULL
157         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
158         // Same as the above (there exists no lock anymore)
159         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
160         // On failure throws InvalidPositionException
161         MapSector * getSectorNoGenerate(v2s16 p2d);
162         // Gets an existing sector or creates an empty one
163         //MapSector * getSectorCreate(v2s16 p2d);
164
165         /*
166                 This is overloaded by ClientMap and ServerMap to allow
167                 their differing fetch methods.
168         */
169         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
170         virtual MapSector * emergeSector(v2s16 p,
171                         std::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
172
173         // Returns InvalidPositionException if not found
174         MapBlock * getBlockNoCreate(v3s16 p);
175         // Returns NULL if not found
176         MapBlock * getBlockNoCreateNoEx(v3s16 p);
177
178         /* Server overrides */
179         virtual MapBlock * emergeBlock(v3s16 p, bool create_blank=true)
180         { return getBlockNoCreateNoEx(p); }
181
182         inline INodeDefManager * getNodeDefManager() { return m_nodedef; }
183
184         // Returns InvalidPositionException if not found
185         bool isNodeUnderground(v3s16 p);
186
187         bool isValidPosition(v3s16 p);
188
189         // throws InvalidPositionException if not found
190         void setNode(v3s16 p, MapNode & n);
191
192         // Returns a CONTENT_IGNORE node if not found
193         // If is_valid_position is not NULL then this will be set to true if the
194         // position is valid, otherwise false
195         MapNode getNodeNoEx(v3s16 p, bool *is_valid_position = NULL);
196
197         /*
198                 These handle lighting but not faces.
199         */
200         void addNodeAndUpdate(v3s16 p, MapNode n,
201                         std::map<v3s16, MapBlock*> &modified_blocks,
202                         bool remove_metadata = true);
203         void removeNodeAndUpdate(v3s16 p,
204                         std::map<v3s16, MapBlock*> &modified_blocks);
205
206         /*
207                 Wrappers for the latter ones.
208                 These emit events.
209                 Return true if succeeded, false if not.
210         */
211         bool addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata = true);
212         bool removeNodeWithEvent(v3s16 p);
213
214         // Call these before and after saving of many blocks
215         virtual void beginSave() {}
216         virtual void endSave() {}
217
218         virtual void save(ModifiedState save_level) { FATAL_ERROR("FIXME"); }
219
220         // Server implements these.
221         // Client leaves them as no-op.
222         virtual bool saveBlock(MapBlock *block) { return false; }
223         virtual bool deleteBlock(v3s16 blockpos) { return false; }
224
225         /*
226                 Updates usage timers and unloads unused blocks and sectors.
227                 Saves modified blocks before unloading on MAPTYPE_SERVER.
228         */
229         void timerUpdate(float dtime, float unload_timeout, u32 max_loaded_blocks,
230                         std::vector<v3s16> *unloaded_blocks=NULL);
231
232         /*
233                 Unloads all blocks with a zero refCount().
234                 Saves modified blocks before unloading on MAPTYPE_SERVER.
235         */
236         void unloadUnreferencedBlocks(std::vector<v3s16> *unloaded_blocks=NULL);
237
238         // Deletes sectors and their blocks from memory
239         // Takes cache into account
240         // If deleted sector is in sector cache, clears cache
241         void deleteSectors(std::vector<v2s16> &list);
242
243         // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
244         virtual void PrintInfo(std::ostream &out);
245
246         void transformLiquids(std::map<v3s16, MapBlock*> & modified_blocks,
247                         ServerEnvironment *env);
248
249         /*
250                 Node metadata
251                 These are basically coordinate wrappers to MapBlock
252         */
253
254         std::vector<v3s16> findNodesWithMetadata(v3s16 p1, v3s16 p2);
255         NodeMetadata *getNodeMetadata(v3s16 p);
256
257         /**
258          * Sets metadata for a node.
259          * This method sets the metadata for a given node.
260          * On success, it returns @c true and the object pointed to
261          * by @p meta is then managed by the system and should
262          * not be deleted by the caller.
263          *
264          * In case of failure, the method returns @c false and the
265          * caller is still responsible for deleting the object!
266          *
267          * @param p node coordinates
268          * @param meta pointer to @c NodeMetadata object
269          * @return @c true on success, false on failure
270          */
271         bool setNodeMetadata(v3s16 p, NodeMetadata *meta);
272         void removeNodeMetadata(v3s16 p);
273
274         /*
275                 Node Timers
276                 These are basically coordinate wrappers to MapBlock
277         */
278
279         NodeTimer getNodeTimer(v3s16 p);
280         void setNodeTimer(const NodeTimer &t);
281         void removeNodeTimer(v3s16 p);
282
283         /*
284                 Misc.
285         */
286         std::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
287
288         /*
289                 Variables
290         */
291
292         void transforming_liquid_add(v3s16 p);
293         s32 transforming_liquid_size();
294
295         bool isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes);
296 protected:
297         friend class LuaVoxelManip;
298
299         std::ostream &m_dout; // A bit deprecated, could be removed
300
301         IGameDef *m_gamedef;
302
303         std::set<MapEventReceiver*> m_event_receivers;
304
305         std::map<v2s16, MapSector*> m_sectors;
306
307         // Be sure to set this to NULL when the cached sector is deleted
308         MapSector *m_sector_cache = nullptr;
309         v2s16 m_sector_cache_p;
310
311         // Queued transforming water nodes
312         UniqueQueue<v3s16> m_transforming_liquid;
313
314         // This stores the properties of the nodes on the map.
315         INodeDefManager *m_nodedef;
316
317         bool isOccluded(v3s16 p0, v3s16 p1, float step, float stepfac,
318                         float start_off, float end_off, u32 needed_count);
319
320 private:
321         f32 m_transforming_liquid_loop_count_multiplier = 1.0f;
322         u32 m_unprocessed_count = 0;
323         u64 m_inc_trending_up_start_time = 0; // milliseconds
324         bool m_queue_size_timer_started = false;
325 };
326
327 /*
328         ServerMap
329
330         This is the only map class that is able to generate map.
331 */
332
333 class ServerMap : public Map
334 {
335 public:
336         /*
337                 savedir: directory to which map data should be saved
338         */
339         ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge);
340         ~ServerMap();
341
342         s32 mapType() const
343         {
344                 return MAPTYPE_SERVER;
345         }
346
347         /*
348                 Get a sector from somewhere.
349                 - Check memory
350                 - Check disk (doesn't load blocks)
351                 - Create blank one
352         */
353         ServerMapSector *createSector(v2s16 p);
354
355         bool saoPositionOverLimit(const v3f &p);
356
357         /*
358                 Blocks are generated by using these and makeBlock().
359         */
360         bool blockpos_over_mapgen_limit(v3s16 p);
361         bool initBlockMake(v3s16 blockpos, BlockMakeData *data);
362         void finishBlockMake(BlockMakeData *data,
363                 std::map<v3s16, MapBlock*> *changed_blocks);
364
365         /*
366                 Get a block from somewhere.
367                 - Memory
368                 - Create blank
369         */
370         MapBlock *createBlock(v3s16 p);
371
372         /*
373                 Forcefully get a block from somewhere.
374                 - Memory
375                 - Load from disk
376                 - Create blank filled with CONTENT_IGNORE
377
378         */
379         MapBlock *emergeBlock(v3s16 p, bool create_blank=true);
380
381         /*
382                 Try to get a block.
383                 If it does not exist in memory, add it to the emerge queue.
384                 - Memory
385                 - Emerge Queue (deferred disk or generate)
386         */
387         MapBlock *getBlockOrEmerge(v3s16 p3d);
388
389         // Helper for placing objects on ground level
390         s16 findGroundLevel(v2s16 p2d);
391
392         /*
393                 Misc. helper functions for fiddling with directory and file
394                 names when saving
395         */
396         void createDirs(std::string path);
397         // returns something like "map/sectors/xxxxxxxx"
398         std::string getSectorDir(v2s16 pos, int layout = 2);
399         // dirname: final directory name
400         v2s16 getSectorPos(const std::string &dirname);
401         v3s16 getBlockPos(const std::string &sectordir, const std::string &blockfile);
402         static std::string getBlockFilename(v3s16 p);
403
404         /*
405                 Database functions
406         */
407         static MapDatabase *createDatabase(const std::string &name, const std::string &savedir, Settings &conf);
408
409         // Returns true if the database file does not exist
410         bool loadFromFolders();
411
412         // Call these before and after saving of blocks
413         void beginSave();
414         void endSave();
415
416         void save(ModifiedState save_level);
417         void listAllLoadableBlocks(std::vector<v3s16> &dst);
418         void listAllLoadedBlocks(std::vector<v3s16> &dst);
419
420         MapgenParams *getMapgenParams();
421
422         /*void saveChunkMeta();
423         void loadChunkMeta();*/
424
425         // The sector mutex should be locked when calling most of these
426
427         // This only saves sector-specific data such as the heightmap
428         // (no MapBlocks)
429         // DEPRECATED? Sectors have no metadata anymore.
430         void saveSectorMeta(ServerMapSector *sector);
431         MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
432         bool loadSectorMeta(v2s16 p2d);
433
434         bool saveBlock(MapBlock *block);
435         static bool saveBlock(MapBlock *block, MapDatabase *db);
436         // This will generate a sector with getSector if not found.
437         void loadBlock(const std::string &sectordir, const std::string &blockfile,
438                         MapSector *sector, bool save_after_load=false);
439         MapBlock* loadBlock(v3s16 p);
440         // Database version
441         void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
442
443         bool deleteBlock(v3s16 blockpos);
444
445         void updateVManip(v3s16 pos);
446
447         // For debug printing
448         virtual void PrintInfo(std::ostream &out);
449
450         bool isSavingEnabled(){ return m_map_saving_enabled; }
451
452         u64 getSeed();
453         s16 getWaterLevel();
454
455         /*!
456          * Fixes lighting in one map block.
457          * May modify other blocks as well, as light can spread
458          * out of the specified block.
459          * Returns false if the block is not generated (so nothing
460          * changed), true otherwise.
461          */
462         bool repairBlockLight(v3s16 blockpos,
463                 std::map<v3s16, MapBlock *> *modified_blocks);
464
465         MapSettingsManager settings_mgr;
466
467 private:
468         // Emerge manager
469         EmergeManager *m_emerge;
470
471         std::string m_savedir;
472         bool m_map_saving_enabled;
473
474 #if 0
475         // Chunk size in MapSectors
476         // If 0, chunks are disabled.
477         s16 m_chunksize;
478         // Chunks
479         core::map<v2s16, MapChunk*> m_chunks;
480 #endif
481
482         /*
483                 Metadata is re-written on disk only if this is true.
484                 This is reset to false when written on disk.
485         */
486         bool m_map_metadata_changed = true;
487         MapDatabase *dbase = nullptr;
488 };
489
490
491 #define VMANIP_BLOCK_DATA_INEXIST     1
492 #define VMANIP_BLOCK_CONTAINS_CIGNORE 2
493
494 class MMVManip : public VoxelManipulator
495 {
496 public:
497         MMVManip(Map *map);
498         virtual ~MMVManip();
499
500         virtual void clear()
501         {
502                 VoxelManipulator::clear();
503                 m_loaded_blocks.clear();
504         }
505
506         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
507                 bool load_if_inexistent = true);
508
509         // This is much faster with big chunks of generated data
510         void blitBackAll(std::map<v3s16, MapBlock*> * modified_blocks,
511                 bool overwrite_generated = true);
512
513         bool m_is_dirty = false;
514
515 protected:
516         Map *m_map;
517         /*
518                 key = blockpos
519                 value = flags describing the block
520         */
521         std::map<v3s16, u8> m_loaded_blocks;
522 };