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