]> git.lizzy.rs Git - minetest.git/blob - src/map.h
ada17cd7e499a039d2e555397a231d8de34bda90
[minetest.git] / src / map.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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 MAP_HEADER
21 #define MAP_HEADER
22
23 #include <jmutex.h>
24 #include <jthread.h>
25 #include <iostream>
26
27 #ifdef _WIN32
28         #include <windows.h>
29         #define sleep_s(x) Sleep((x*1000))
30 #else
31         #include <unistd.h>
32         #define sleep_s(x) sleep(x)
33 #endif
34
35 #include "common_irrlicht.h"
36 #include "mapnode.h"
37 #include "mapblock.h"
38 #include "mapsector.h"
39 #include "constants.h"
40 #include "voxel.h"
41 #include "mapchunk.h"
42 #include "nodemetadata.h"
43
44 /*
45         MapEditEvent
46 */
47
48 #define MAPTYPE_BASE 0
49 #define MAPTYPE_SERVER 1
50 #define MAPTYPE_CLIENT 2
51
52 enum MapEditEventType{
53         // Node added (changed from air or something else to something)
54         MEET_ADDNODE,
55         // Node removed (changed to air)
56         MEET_REMOVENODE,
57         // Node metadata of block changed (not knowing which node exactly)
58         // p stores block coordinate
59         MEET_BLOCK_NODE_METADATA_CHANGED,
60         // Anything else
61         MEET_OTHER
62 };
63
64 struct MapEditEvent
65 {
66         MapEditEventType type;
67         v3s16 p;
68         MapNode n;
69         core::map<v3s16, bool> modified_blocks;
70         u16 already_known_by_peer;
71
72         MapEditEvent():
73                 type(MEET_OTHER),
74                 already_known_by_peer(0)
75         {
76         }
77         
78         MapEditEvent * clone()
79         {
80                 MapEditEvent *event = new MapEditEvent();
81                 event->type = type;
82                 event->p = p;
83                 event->n = n;
84                 for(core::map<v3s16, bool>::Iterator
85                                 i = modified_blocks.getIterator();
86                                 i.atEnd()==false; i++)
87                 {
88                         v3s16 p = i.getNode()->getKey();
89                         bool v = i.getNode()->getValue();
90                         event->modified_blocks.insert(p, v);
91                 }
92                 return event;
93         }
94 };
95
96 class MapEventReceiver
97 {
98 public:
99         // event shall be deleted by caller after the call.
100         virtual void onMapEditEvent(MapEditEvent *event) = 0;
101 };
102
103 class Map : public NodeContainer
104 {
105 public:
106
107         Map(std::ostream &dout);
108         virtual ~Map();
109
110         virtual u16 nodeContainerId() const
111         {
112                 return NODECONTAINER_ID_MAP;
113         }
114
115         virtual s32 mapType() const
116         {
117                 return MAPTYPE_BASE;
118         }
119         
120         /*
121                 Drop (client) or delete (server) the map.
122         */
123         virtual void drop()
124         {
125                 delete this;
126         }
127
128         void addEventReceiver(MapEventReceiver *event_receiver);
129         void removeEventReceiver(MapEventReceiver *event_receiver);
130         // event shall be deleted by caller after the call.
131         void dispatchEvent(MapEditEvent *event);
132
133         // On failure returns NULL
134         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
135         // Same as the above (there exists no lock anymore)
136         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
137         // On failure throws InvalidPositionException
138         MapSector * getSectorNoGenerate(v2s16 p2d);
139         // Gets an existing sector or creates an empty one
140         //MapSector * getSectorCreate(v2s16 p2d);
141
142         /*
143                 This is overloaded by ClientMap and ServerMap to allow
144                 their differing fetch methods.
145         */
146         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
147         virtual MapSector * emergeSector(v2s16 p,
148                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
149
150         // Returns InvalidPositionException if not found
151         MapBlock * getBlockNoCreate(v3s16 p);
152         // Returns NULL if not found
153         MapBlock * getBlockNoCreateNoEx(v3s16 p);
154         // Gets an existing block or creates an empty one
155         //MapBlock * getBlockCreate(v3s16 p);
156         
157         // Returns InvalidPositionException if not found
158         bool isNodeUnderground(v3s16 p);
159         
160         // virtual from NodeContainer
161         bool isValidPosition(v3s16 p)
162         {
163                 v3s16 blockpos = getNodeBlockPos(p);
164                 MapBlock *blockref;
165                 try{
166                         blockref = getBlockNoCreate(blockpos);
167                 }
168                 catch(InvalidPositionException &e)
169                 {
170                         return false;
171                 }
172                 return true;
173                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
174                 bool is_valid = blockref->isValidPosition(relpos);
175                 return is_valid;*/
176         }
177         
178         // virtual from NodeContainer
179         // throws InvalidPositionException if not found
180         MapNode getNode(v3s16 p)
181         {
182                 v3s16 blockpos = getNodeBlockPos(p);
183                 MapBlock * blockref = getBlockNoCreate(blockpos);
184                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
185
186                 return blockref->getNodeNoCheck(relpos);
187         }
188
189         // virtual from NodeContainer
190         // throws InvalidPositionException if not found
191         void setNode(v3s16 p, MapNode & n)
192         {
193                 v3s16 blockpos = getNodeBlockPos(p);
194                 MapBlock * blockref = getBlockNoCreate(blockpos);
195                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
196                 blockref->setNodeNoCheck(relpos, n);
197         }
198         
199         // Returns a CONTENT_IGNORE node if not found
200         MapNode getNodeNoEx(v3s16 p)
201         {
202                 try{
203                         v3s16 blockpos = getNodeBlockPos(p);
204                         MapBlock * blockref = getBlockNoCreate(blockpos);
205                         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
206
207                         return blockref->getNodeNoCheck(relpos);
208                 }
209                 catch(InvalidPositionException &e)
210                 {
211                         return MapNode(CONTENT_IGNORE);
212                 }
213         }
214
215         void unspreadLight(enum LightBank bank,
216                         core::map<v3s16, u8> & from_nodes,
217                         core::map<v3s16, bool> & light_sources,
218                         core::map<v3s16, MapBlock*> & modified_blocks);
219
220         void unLightNeighbors(enum LightBank bank,
221                         v3s16 pos, u8 lightwas,
222                         core::map<v3s16, bool> & light_sources,
223                         core::map<v3s16, MapBlock*> & modified_blocks);
224         
225         void spreadLight(enum LightBank bank,
226                         core::map<v3s16, bool> & from_nodes,
227                         core::map<v3s16, MapBlock*> & modified_blocks);
228         
229         void lightNeighbors(enum LightBank bank,
230                         v3s16 pos,
231                         core::map<v3s16, MapBlock*> & modified_blocks);
232
233         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
234
235         s16 propagateSunlight(v3s16 start,
236                         core::map<v3s16, MapBlock*> & modified_blocks);
237         
238         void updateLighting(enum LightBank bank,
239                         core::map<v3s16, MapBlock*>  & a_blocks,
240                         core::map<v3s16, MapBlock*> & modified_blocks);
241                         
242         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
243                         core::map<v3s16, MapBlock*> & modified_blocks);
244                         
245         /*
246                 These handle lighting but not faces.
247         */
248         void addNodeAndUpdate(v3s16 p, MapNode n,
249                         core::map<v3s16, MapBlock*> &modified_blocks);
250         void removeNodeAndUpdate(v3s16 p,
251                         core::map<v3s16, MapBlock*> &modified_blocks);
252
253         /*
254                 Wrappers for the latter ones.
255                 These emit events.
256                 Return true if succeeded, false if not.
257         */
258         bool addNodeWithEvent(v3s16 p, MapNode n);
259         bool removeNodeWithEvent(v3s16 p);
260         
261         /*
262                 Takes the blocks at the edges into account
263         */
264         bool dayNightDiffed(v3s16 blockpos);
265
266         //core::aabbox3d<s16> getDisplayedBlockArea();
267
268         //bool updateChangedVisibleArea();
269         
270         virtual void save(bool only_changed){assert(0);};
271         
272         // Server implements this
273         virtual void saveBlock(MapBlock *block){};
274
275         /*
276                 Updates usage timers
277         */
278         void timerUpdate(float dtime);
279         
280         // Takes cache into account
281         // sector mutex should be locked when calling
282         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
283         
284         // Returns count of deleted sectors
285         u32 unloadUnusedData(float timeout, bool only_blocks=false,
286                         core::list<v3s16> *deleted_blocks=NULL);
287
288         // For debug printing
289         virtual void PrintInfo(std::ostream &out);
290         
291         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
292
293         /*
294                 Node metadata
295                 These are basically coordinate wrappers to MapBlock
296         */
297         
298         NodeMetadata* getNodeMetadata(v3s16 p);
299         void setNodeMetadata(v3s16 p, NodeMetadata *meta);
300         void removeNodeMetadata(v3s16 p);
301         void nodeMetadataStep(float dtime,
302                         core::map<v3s16, MapBlock*> &changed_blocks);
303         
304         /*
305                 Misc.
306         */
307         core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
308
309         /*
310                 Variables
311         */
312         
313 protected:
314
315         std::ostream &m_dout;
316
317         core::map<MapEventReceiver*, bool> m_event_receivers;
318         
319         core::map<v2s16, MapSector*> m_sectors;
320         //JMutex m_sector_mutex;
321
322         // Be sure to set this to NULL when the cached sector is deleted 
323         MapSector *m_sector_cache;
324         v2s16 m_sector_cache_p;
325
326         // Queued transforming water nodes
327         UniqueQueue<v3s16> m_transforming_liquid;
328 };
329
330 /*
331         ServerMap
332
333         This is the only map class that is able to generate map.
334 */
335
336 //struct ChunkMakeData;
337
338 struct BlockMakeData;
339
340 class ServerMap : public Map
341 {
342 public:
343         /*
344                 savedir: directory to which map data should be saved
345         */
346         ServerMap(std::string savedir);
347         ~ServerMap();
348
349         s32 mapType() const
350         {
351                 return MAPTYPE_SERVER;
352         }
353
354         /*
355                 Get a sector from somewhere.
356                 - Check memory
357                 - Check disk (doesn't load blocks)
358                 - Create blank one
359         */
360         ServerMapSector * createSector(v2s16 p);
361
362         /*
363                 Blocks are generated by using these and makeBlock().
364         */
365         void initBlockMake(BlockMakeData *data, v3s16 blockpos);
366         MapBlock* finishBlockMake(BlockMakeData *data,
367                         core::map<v3s16, MapBlock*> &changed_blocks);
368         
369         // A non-threaded wrapper to the above
370         MapBlock * generateBlock(
371                         v3s16 p,
372                         core::map<v3s16, MapBlock*> &modified_blocks
373         );
374         
375         /*
376                 Get a block from somewhere.
377                 - Memory
378                 - Create blank
379         */
380         MapBlock * createBlock(v3s16 p);
381
382 #if 0
383         /*
384                 NOTE: This comment might be outdated
385                 
386                 Forcefully get a block from somewhere.
387
388                 InvalidPositionException possible if only_from_disk==true
389                 
390                 Parameters:
391                 changed_blocks: Blocks that have been modified
392         */
393         MapBlock * emergeBlock(
394                         v3s16 p,
395                         bool only_from_disk,
396                         core::map<v3s16, MapBlock*> &changed_blocks,
397                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
398         );
399 #endif
400         
401         // Helper for placing objects on ground level
402         s16 findGroundLevel(v2s16 p2d);
403
404         /*
405                 Misc. helper functions for fiddling with directory and file
406                 names when saving
407         */
408         void createDirs(std::string path);
409         // returns something like "map/sectors/xxxxxxxx"
410         std::string getSectorDir(v2s16 pos, int layout = 2);
411         // dirname: final directory name
412         v2s16 getSectorPos(std::string dirname);
413         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
414         static std::string getBlockFilename(v3s16 p);
415
416         void save(bool only_changed);
417         //void loadAll();
418         
419         // Saves map seed and possibly other stuff
420         void saveMapMeta();
421         void loadMapMeta();
422         
423         /*void saveChunkMeta();
424         void loadChunkMeta();*/
425         
426         // The sector mutex should be locked when calling most of these
427         
428         // This only saves sector-specific data such as the heightmap
429         // (no MapBlocks)
430         // DEPRECATED? Sectors have no metadata anymore.
431         void saveSectorMeta(ServerMapSector *sector);
432         MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
433         bool loadSectorMeta(v2s16 p2d);
434         
435         // Full load of a sector including all blocks.
436         // returns true on success, false on failure.
437         bool loadSectorFull(v2s16 p2d);
438         // If sector is not found in memory, try to load it from disk.
439         // Returns true if sector now resides in memory
440         //bool deFlushSector(v2s16 p2d);
441         
442         void saveBlock(MapBlock *block);
443         // This will generate a sector with getSector if not found.
444         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
445         MapBlock* loadBlock(v3s16 p);
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(){ return m_seed; }
453
454 private:
455         // Seed used for all kinds of randomness
456         u64 m_seed;
457
458         std::string m_savedir;
459         bool m_map_saving_enabled;
460
461 #if 0
462         // Chunk size in MapSectors
463         // If 0, chunks are disabled.
464         s16 m_chunksize;
465         // Chunks
466         core::map<v2s16, MapChunk*> m_chunks;
467 #endif
468
469         /*
470                 Metadata is re-written on disk only if this is true.
471                 This is reset to false when written on disk.
472         */
473         bool m_map_metadata_changed;
474 };
475
476 /*
477         ClientMap stuff
478 */
479
480 #ifndef SERVER
481
482 struct MapDrawControl
483 {
484         MapDrawControl():
485                 range_all(false),
486                 wanted_range(50),
487                 wanted_max_blocks(0),
488                 wanted_min_range(0),
489                 blocks_drawn(0),
490                 blocks_would_have_drawn(0)
491         {
492         }
493         // Overrides limits by drawing everything
494         bool range_all;
495         // Wanted drawing range
496         float wanted_range;
497         // Maximum number of blocks to draw
498         u32 wanted_max_blocks;
499         // Blocks in this range are drawn regardless of number of blocks drawn
500         float wanted_min_range;
501         // Number of blocks rendered is written here by the renderer
502         u32 blocks_drawn;
503         // Number of blocks that would have been drawn in wanted_range
504         u32 blocks_would_have_drawn;
505 };
506
507 class Client;
508
509 /*
510         ClientMap
511         
512         This is the only map class that is able to render itself on screen.
513 */
514
515 class ClientMap : public Map, public scene::ISceneNode
516 {
517 public:
518         ClientMap(
519                         Client *client,
520                         MapDrawControl &control,
521                         scene::ISceneNode* parent,
522                         scene::ISceneManager* mgr,
523                         s32 id
524         );
525
526         ~ClientMap();
527
528         s32 mapType() const
529         {
530                 return MAPTYPE_CLIENT;
531         }
532
533         void drop()
534         {
535                 ISceneNode::drop();
536         }
537
538         void updateCamera(v3f pos, v3f dir)
539         {
540                 JMutexAutoLock lock(m_camera_mutex);
541                 m_camera_position = pos;
542                 m_camera_direction = dir;
543         }
544
545         /*
546                 Forcefully get a sector from somewhere
547         */
548         MapSector * emergeSector(v2s16 p);
549
550         void deSerializeSector(v2s16 p2d, std::istream &is);
551
552         /*
553                 ISceneNode methods
554         */
555
556         virtual void OnRegisterSceneNode();
557
558         virtual void render()
559         {
560                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
561                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
562                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
563         }
564         
565         virtual const core::aabbox3d<f32>& getBoundingBox() const
566         {
567                 return m_box;
568         }
569
570         void renderMap(video::IVideoDriver* driver, s32 pass);
571
572         /*
573                 Methods for setting temporary modifications to nodes for
574                 drawing.
575
576                 Returns true if something changed.
577                 
578                 All blocks whose mesh could have been changed are inserted
579                 to affected_blocks.
580         */
581         bool setTempMod(v3s16 p, NodeMod mod,
582                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
583         bool clearTempMod(v3s16 p,
584                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
585         // Efficient implementation needs a cache of TempMods
586         //void clearTempMods();
587
588         void expireMeshes(bool only_daynight_diffed);
589         
590         /*
591                 Update the faces of the given block and blocks on the
592                 leading edge.
593         */
594         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
595         
596         // Update meshes that touch the node
597         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
598
599         // For debug printing
600         virtual void PrintInfo(std::ostream &out);
601         
602         // Check if sector was drawn on last render()
603         bool sectorWasDrawn(v2s16 p)
604         {
605                 return (m_last_drawn_sectors.find(p) != NULL);
606         }
607         
608 private:
609         Client *m_client;
610         
611         core::aabbox3d<f32> m_box;
612         
613         // This is the master heightmap mesh
614         //scene::SMesh *mesh;
615         //JMutex mesh_mutex;
616         
617         MapDrawControl &m_control;
618
619         v3f m_camera_position;
620         v3f m_camera_direction;
621         JMutex m_camera_mutex;
622         
623         core::map<v2s16, bool> m_last_drawn_sectors;
624 };
625
626 #endif
627
628 class MapVoxelManipulator : public VoxelManipulator
629 {
630 public:
631         MapVoxelManipulator(Map *map);
632         virtual ~MapVoxelManipulator();
633         
634         virtual void clear()
635         {
636                 VoxelManipulator::clear();
637                 m_loaded_blocks.clear();
638         }
639
640         virtual void emerge(VoxelArea a, s32 caller_id=-1);
641
642         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
643
644 protected:
645         Map *m_map;
646         /*
647                 key = blockpos
648                 value = block existed when loaded
649         */
650         core::map<v3s16, bool> m_loaded_blocks;
651 };
652
653 class ManualMapVoxelManipulator : public MapVoxelManipulator
654 {
655 public:
656         ManualMapVoxelManipulator(Map *map);
657         virtual ~ManualMapVoxelManipulator();
658
659         void setMap(Map *map)
660         {m_map = map;}
661         
662         virtual void emerge(VoxelArea a, s32 caller_id=-1);
663
664         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
665         
666         // This is much faster with big chunks of generated data
667         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
668
669 protected:
670         bool m_create_area;
671 };
672
673 #if 0
674 struct ChunkMakeData
675 {
676         bool no_op;
677         ManualMapVoxelManipulator vmanip;
678         u64 seed;
679         v2s16 chunkpos;
680         s16 y_blocks_min;
681         s16 y_blocks_max;
682         v2s16 sectorpos_base;
683         s16 sectorpos_base_size;
684         v2s16 sectorpos_bigbase;
685         s16 sectorpos_bigbase_size;
686         s16 max_spread_amount;
687         UniqueQueue<v3s16> transforming_liquid;
688
689         ChunkMakeData():
690                 no_op(false),
691                 vmanip(NULL),
692                 seed(0)
693         {}
694 };
695
696 void makeChunk(ChunkMakeData *data);
697 #endif
698
699 struct BlockMakeData
700 {
701         bool no_op;
702         ManualMapVoxelManipulator vmanip;
703         u64 seed;
704         v3s16 blockpos;
705         UniqueQueue<v3s16> transforming_liquid;
706
707         BlockMakeData():
708                 no_op(false),
709                 vmanip(NULL),
710                 seed(0)
711         {}
712 };
713
714 void makeBlock(BlockMakeData *data);
715
716 #endif
717