2fafcae17e1fef95540be8f4ed56768880cae988
[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* getNodeMetadataClone(v3s16 p);
286
287         /*
288                 Variables
289         */
290         
291 protected:
292
293         std::ostream &m_dout;
294
295         core::map<MapEventReceiver*, bool> m_event_receivers;
296         
297         // Mutex is important because on client map is accessed asynchronously
298         core::map<v2s16, MapSector*> m_sectors;
299         JMutex m_sector_mutex;
300
301         // Be sure to set this to NULL when the cached sector is deleted 
302         MapSector *m_sector_cache;
303         v2s16 m_sector_cache_p;
304
305         //WrapperHeightmap m_hwrapper;
306         
307         // Queued transforming water nodes
308         UniqueQueue<v3s16> m_transforming_liquid;
309 };
310
311 /*
312         ServerMap
313
314         This is the only map class that is able to generate map.
315 */
316
317 class ServerMap : public Map
318 {
319 public:
320         /*
321                 savedir: directory to which map data should be saved
322         */
323         ServerMap(std::string savedir);
324         ~ServerMap();
325
326         s32 mapType() const
327         {
328                 return MAPTYPE_SERVER;
329         }
330
331         /*
332                 Map generation
333         */
334         
335         // Returns the position of the chunk where the sector is in
336         v2s16 sector_to_chunk(v2s16 sectorpos)
337         {
338                 sectorpos.X += m_chunksize / 2;
339                 sectorpos.Y += m_chunksize / 2;
340                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
341                 return chunkpos;
342         }
343         
344         // Returns the position of the (0,0) sector of the chunk
345         v2s16 chunk_to_sector(v2s16 chunkpos)
346         {
347                 v2s16 sectorpos(
348                         chunkpos.X * m_chunksize,
349                         chunkpos.Y * m_chunksize
350                 );
351                 sectorpos.X -= m_chunksize / 2;
352                 sectorpos.Y -= m_chunksize / 2;
353                 return sectorpos;
354         }
355
356         /*
357                 Get a chunk.
358         */
359         MapChunk *getChunk(v2s16 chunkpos)
360         {
361                 core::map<v2s16, MapChunk*>::Node *n;
362                 n = m_chunks.find(chunkpos);
363                 if(n == NULL)
364                         return NULL;
365                 return n->getValue();
366         }
367
368         /*
369                 True if the chunk and its neighbors are fully generated.
370                 It means the chunk will not be touched in the future by the
371                 generator. If false, generateChunk will make it true.
372         */
373         bool chunkNonVolatile(v2s16 chunkpos)
374         {
375                 /*for(s16 x=-1; x<=1; x++)
376                 for(s16 y=-1; y<=1; y++)*/
377                 s16 x=0;
378                 s16 y=0;
379                 {
380                         v2s16 chunkpos0 = chunkpos + v2s16(x,y);
381                         MapChunk *chunk = getChunk(chunkpos);
382                         if(chunk == NULL)
383                                 return false;
384                         if(chunk->getGenLevel() != GENERATED_FULLY)
385                                 return false;
386                 }
387                 return true;
388         }
389
390         /*
391                 Generate a chunk.
392
393                 All chunks touching this one can be altered also.
394         */
395         MapChunk* generateChunkRaw(v2s16 chunkpos,
396                         core::map<v3s16, MapBlock*> &changed_blocks,
397                         bool force=false);
398         
399         /*
400                 Generate a chunk and its neighbors so that it won't be touched
401                 anymore.
402         */
403         MapChunk* generateChunk(v2s16 chunkpos,
404                         core::map<v3s16, MapBlock*> &changed_blocks);
405         
406         /*
407                 Generate a sector.
408                 
409                 This is mainly called by generateChunkRaw.
410         */
411         //ServerMapSector * generateSector(v2s16 p);
412         
413         /*
414                 Get a sector from somewhere.
415                 - Check memory
416                 - Check disk (loads blocks also)
417                 - Create blank one
418         */
419         ServerMapSector * createSector(v2s16 p);
420
421         /*
422                 Get a sector from somewhere.
423                 - Check memory
424                 - Check disk (loads blocks also)
425                 - Generate chunk
426         */
427         MapSector * emergeSector(v2s16 p,
428                         core::map<v3s16, MapBlock*> &changed_blocks);
429         
430         MapSector * emergeSector(v2s16 p)
431         {
432                 core::map<v3s16, MapBlock*> changed_blocks;
433                 return emergeSector(p, changed_blocks);
434         }
435
436         MapBlock * generateBlock(
437                         v3s16 p,
438                         MapBlock *original_dummy,
439                         ServerMapSector *sector,
440                         core::map<v3s16, MapBlock*> &changed_blocks,
441                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
442         );
443         
444         /*
445                 Get a block from somewhere.
446                 - Memory
447                 - Create blank
448         */
449         MapBlock * createBlock(v3s16 p);
450         
451         /*
452                 only_from_disk, changed_blocks and lighting_invalidated_blocks
453                 are not properly used by the new map generator.
454         */
455         MapBlock * emergeBlock(
456                         v3s16 p,
457                         bool only_from_disk,
458                         core::map<v3s16, MapBlock*> &changed_blocks,
459                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
460         );
461
462 #if 0
463         /*
464                 Forcefully get a block from somewhere.
465
466                 Exceptions:
467                 - InvalidPositionException: possible if only_from_disk==true
468                 
469                 changed_blocks:
470                 - All already existing blocks that were modified are added.
471                         - If found on disk, nothing will be added.
472                         - If generated, the new block will not be included.
473
474                 lighting_invalidated_blocks:
475                 - All blocks that have heavy-to-calculate lighting changes
476                   are added.
477                         - updateLighting() should be called for these.
478                 
479                 - A block that is in changed_blocks may not be in
480                   lighting_invalidated_blocks.
481         */
482         MapBlock * emergeBlock(
483                         v3s16 p,
484                         bool only_from_disk,
485                         core::map<v3s16, MapBlock*> &changed_blocks,
486                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
487         );
488 #endif
489         
490         // Helper for placing objects on ground level
491         s16 findGroundLevel(v2s16 p2d);
492
493         /*
494                 Misc. helper functions for fiddling with directory and file
495                 names when saving
496         */
497         void createDir(std::string path);
498         void createSaveDir();
499         // returns something like "xxxxxxxx"
500         std::string getSectorSubDir(v2s16 pos);
501         // returns something like "map/sectors/xxxxxxxx"
502         std::string getSectorDir(v2s16 pos);
503         std::string createSectorDir(v2s16 pos);
504         // dirname: final directory name
505         v2s16 getSectorPos(std::string dirname);
506         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
507
508         void save(bool only_changed);
509         void loadAll();
510         
511         // Saves map seed and possibly other stuff
512         void saveMapMeta();
513         void loadMapMeta();
514         
515         void saveChunkMeta();
516         void loadChunkMeta();
517         
518         // The sector mutex should be locked when calling most of these
519         
520         // This only saves sector-specific data such as the heightmap
521         // (no MapBlocks)
522         // DEPRECATED? Sectors have no metadata anymore.
523         void saveSectorMeta(ServerMapSector *sector);
524         MapSector* loadSectorMeta(std::string dirname);
525         
526         // Full load of a sector including all blocks.
527         // returns true on success, false on failure.
528         bool loadSectorFull(v2s16 p2d);
529         // If sector is not found in memory, try to load it from disk.
530         // Returns true if sector now resides in memory
531         //bool deFlushSector(v2s16 p2d);
532         
533         void saveBlock(MapBlock *block);
534         // This will generate a sector with getSector if not found.
535         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
536
537         // For debug printing
538         virtual void PrintInfo(std::ostream &out);
539
540         bool isSavingEnabled(){ return m_map_saving_enabled; }
541
542 private:
543         // Seed used for all kinds of randomness
544         u64 m_seed;
545
546         std::string m_savedir;
547         bool m_map_saving_enabled;
548
549         // Chunk size in MapSectors
550         s16 m_chunksize;
551         // Chunks
552         core::map<v2s16, MapChunk*> m_chunks;
553 };
554
555 /*
556         ClientMap stuff
557 */
558
559 #ifndef SERVER
560
561 struct MapDrawControl
562 {
563         MapDrawControl():
564                 range_all(false),
565                 wanted_range(50),
566                 wanted_max_blocks(0),
567                 wanted_min_range(0),
568                 blocks_drawn(0),
569                 blocks_would_have_drawn(0)
570         {
571         }
572         // Overrides limits by drawing everything
573         bool range_all;
574         // Wanted drawing range
575         float wanted_range;
576         // Maximum number of blocks to draw
577         u32 wanted_max_blocks;
578         // Blocks in this range are drawn regardless of number of blocks drawn
579         float wanted_min_range;
580         // Number of blocks rendered is written here by the renderer
581         u32 blocks_drawn;
582         // Number of blocks that would have been drawn in wanted_range
583         u32 blocks_would_have_drawn;
584 };
585
586 class Client;
587
588 /*
589         ClientMap
590         
591         This is the only map class that is able to render itself on screen.
592 */
593
594 class ClientMap : public Map, public scene::ISceneNode
595 {
596 public:
597         ClientMap(
598                         Client *client,
599                         MapDrawControl &control,
600                         scene::ISceneNode* parent,
601                         scene::ISceneManager* mgr,
602                         s32 id
603         );
604
605         ~ClientMap();
606
607         s32 mapType() const
608         {
609                 return MAPTYPE_CLIENT;
610         }
611
612         void drop()
613         {
614                 ISceneNode::drop();
615         }
616
617         void updateCamera(v3f pos, v3f dir)
618         {
619                 JMutexAutoLock lock(m_camera_mutex);
620                 m_camera_position = pos;
621                 m_camera_direction = dir;
622         }
623
624         /*
625                 Forcefully get a sector from somewhere
626         */
627         MapSector * emergeSector(v2s16 p);
628
629         void deSerializeSector(v2s16 p2d, std::istream &is);
630
631         /*
632                 ISceneNode methods
633         */
634
635         virtual void OnRegisterSceneNode();
636
637         virtual void render()
638         {
639                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
640                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
641                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
642         }
643         
644         virtual const core::aabbox3d<f32>& getBoundingBox() const
645         {
646                 return m_box;
647         }
648
649         void renderMap(video::IVideoDriver* driver, s32 pass);
650
651         /*
652                 Methods for setting temporary modifications to nodes for
653                 drawing.
654
655                 Returns true if something changed.
656                 
657                 All blocks whose mesh could have been changed are inserted
658                 to affected_blocks.
659         */
660         bool setTempMod(v3s16 p, NodeMod mod,
661                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
662         bool clearTempMod(v3s16 p,
663                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
664         // Efficient implementation needs a cache of TempMods
665         //void clearTempMods();
666
667         void expireMeshes(bool only_daynight_diffed);
668         
669         /*
670                 Update the faces of the given block and blocks on the
671                 leading edge.
672         */
673         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
674         
675         // Update meshes that touch the node
676         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
677
678         // For debug printing
679         virtual void PrintInfo(std::ostream &out);
680         
681 private:
682         Client *m_client;
683         
684         core::aabbox3d<f32> m_box;
685         
686         // This is the master heightmap mesh
687         //scene::SMesh *mesh;
688         //JMutex mesh_mutex;
689         
690         MapDrawControl &m_control;
691
692         v3f m_camera_position;
693         v3f m_camera_direction;
694         JMutex m_camera_mutex;
695
696 };
697
698 #endif
699
700 class MapVoxelManipulator : public VoxelManipulator
701 {
702 public:
703         MapVoxelManipulator(Map *map);
704         virtual ~MapVoxelManipulator();
705         
706         virtual void clear()
707         {
708                 VoxelManipulator::clear();
709                 m_loaded_blocks.clear();
710         }
711
712         virtual void emerge(VoxelArea a, s32 caller_id=-1);
713
714         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
715
716 protected:
717         Map *m_map;
718         /*
719                 key = blockpos
720                 value = block existed when loaded
721         */
722         core::map<v3s16, bool> m_loaded_blocks;
723 };
724
725 class ManualMapVoxelManipulator : public MapVoxelManipulator
726 {
727 public:
728         ManualMapVoxelManipulator(Map *map);
729         virtual ~ManualMapVoxelManipulator();
730         
731         virtual void emerge(VoxelArea a, s32 caller_id=-1);
732
733         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
734         
735         // This is much faster with big chunks of generated data
736         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
737
738 protected:
739         bool m_create_area;
740 };
741
742 #endif
743