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