some fixes to make compiling on some bsd easier
[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 "heightmap.h"
37 #include "mapnode.h"
38 #include "mapblock.h"
39 #include "mapsector.h"
40 #include "constants.h"
41 #include "voxel.h"
42 #include "mapchunk.h"
43
44 #define MAPTYPE_BASE 0
45 #define MAPTYPE_SERVER 1
46 #define MAPTYPE_CLIENT 2
47
48 class Map : public NodeContainer
49 {
50 public:
51
52         Map(std::ostream &dout);
53         virtual ~Map();
54
55         virtual u16 nodeContainerId() const
56         {
57                 return NODECONTAINER_ID_MAP;
58         }
59
60         virtual s32 mapType() const
61         {
62                 return MAPTYPE_BASE;
63         }
64
65         virtual void drop()
66         {
67                 delete this;
68         }
69
70         void updateCamera(v3f pos, v3f dir)
71         {
72                 JMutexAutoLock lock(m_camera_mutex);
73                 m_camera_position = pos;
74                 m_camera_direction = dir;
75         }
76
77         static core::aabbox3d<f32> getNodeBox(v3s16 p)
78         {
79                 return core::aabbox3d<f32>(
80                         (float)p.X * BS - 0.5*BS,
81                         (float)p.Y * BS - 0.5*BS,
82                         (float)p.Z * BS - 0.5*BS,
83                         (float)p.X * BS + 0.5*BS,
84                         (float)p.Y * BS + 0.5*BS,
85                         (float)p.Z * BS + 0.5*BS
86                 );
87         }
88         
89         // On failure returns NULL
90         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
91         // On failure returns NULL
92         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
93         // On failure throws InvalidPositionException
94         MapSector * getSectorNoGenerate(v2s16 p2d);
95         // Gets an existing sector or creates an empty one
96         //MapSector * getSectorCreate(v2s16 p2d);
97
98         /*
99                 This is overloaded by ClientMap and ServerMap to allow
100                 their differing fetch methods.
101         */
102         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
103         virtual MapSector * emergeSector(v2s16 p,
104                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
105
106         // Returns InvalidPositionException if not found
107         MapBlock * getBlockNoCreate(v3s16 p);
108         // Returns NULL if not found
109         MapBlock * getBlockNoCreateNoEx(v3s16 p);
110         // Gets an existing block or creates an empty one
111         //MapBlock * getBlockCreate(v3s16 p);
112         
113         // Returns InvalidPositionException if not found
114         f32 getGroundHeight(v2s16 p, bool generate=false);
115         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
116
117         // Returns InvalidPositionException if not found
118         bool isNodeUnderground(v3s16 p);
119         
120         // virtual from NodeContainer
121         bool isValidPosition(v3s16 p)
122         {
123                 v3s16 blockpos = getNodeBlockPos(p);
124                 MapBlock *blockref;
125                 try{
126                         blockref = getBlockNoCreate(blockpos);
127                 }
128                 catch(InvalidPositionException &e)
129                 {
130                         return false;
131                 }
132                 return true;
133                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
134                 bool is_valid = blockref->isValidPosition(relpos);
135                 return is_valid;*/
136         }
137         
138         // virtual from NodeContainer
139         // throws InvalidPositionException if not found
140         MapNode getNode(v3s16 p)
141         {
142                 v3s16 blockpos = getNodeBlockPos(p);
143                 MapBlock * blockref = getBlockNoCreate(blockpos);
144                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
145
146                 return blockref->getNodeNoCheck(relpos);
147         }
148
149         // virtual from NodeContainer
150         // throws InvalidPositionException if not found
151         void setNode(v3s16 p, MapNode & n)
152         {
153                 v3s16 blockpos = getNodeBlockPos(p);
154                 MapBlock * blockref = getBlockNoCreate(blockpos);
155                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
156                 blockref->setNodeNoCheck(relpos, n);
157         }
158
159         /*MapNode getNodeGenerate(v3s16 p)
160         {
161                 v3s16 blockpos = getNodeBlockPos(p);
162                 MapBlock * blockref = getBlock(blockpos);
163                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
164
165                 return blockref->getNode(relpos);
166         }*/
167
168         /*void setNodeGenerate(v3s16 p, MapNode & n)
169         {
170                 v3s16 blockpos = getNodeBlockPos(p);
171                 MapBlock * blockref = getBlock(blockpos);
172                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
173                 blockref->setNode(relpos, n);
174         }*/
175
176         void unspreadLight(enum LightBank bank,
177                         core::map<v3s16, u8> & from_nodes,
178                         core::map<v3s16, bool> & light_sources,
179                         core::map<v3s16, MapBlock*> & modified_blocks);
180
181         void unLightNeighbors(enum LightBank bank,
182                         v3s16 pos, u8 lightwas,
183                         core::map<v3s16, bool> & light_sources,
184                         core::map<v3s16, MapBlock*> & modified_blocks);
185         
186         void spreadLight(enum LightBank bank,
187                         core::map<v3s16, bool> & from_nodes,
188                         core::map<v3s16, MapBlock*> & modified_blocks);
189         
190         void lightNeighbors(enum LightBank bank,
191                         v3s16 pos,
192                         core::map<v3s16, MapBlock*> & modified_blocks);
193
194         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
195
196         s16 propagateSunlight(v3s16 start,
197                         core::map<v3s16, MapBlock*> & modified_blocks);
198         
199         void updateLighting(enum LightBank bank,
200                         core::map<v3s16, MapBlock*>  & a_blocks,
201                         core::map<v3s16, MapBlock*> & modified_blocks);
202                         
203         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
204                         core::map<v3s16, MapBlock*> & modified_blocks);
205                         
206         /*
207                 These handle lighting but not faces.
208         */
209         void addNodeAndUpdate(v3s16 p, MapNode n,
210                         core::map<v3s16, MapBlock*> &modified_blocks);
211         void removeNodeAndUpdate(v3s16 p,
212                         core::map<v3s16, MapBlock*> &modified_blocks);
213         
214 #ifndef SERVER
215         void expireMeshes(bool only_daynight_diffed);
216         
217         /*
218                 Update the faces of the given block and blocks on the
219                 leading edge.
220         */
221         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
222         
223         // Update meshes that touch the node
224         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
225 #endif
226
227         /*
228                 Takes the blocks at the edges into account
229         */
230         bool dayNightDiffed(v3s16 blockpos);
231
232         //core::aabbox3d<s16> getDisplayedBlockArea();
233
234         //bool updateChangedVisibleArea();
235         
236         virtual void save(bool only_changed){assert(0);};
237
238         /*
239                 Updates usage timers
240         */
241         void timerUpdate(float dtime);
242         
243         // Takes cache into account
244         // sector mutex should be locked when calling
245         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
246         
247         // Returns count of deleted sectors
248         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
249                         core::list<v3s16> *deleted_blocks=NULL);
250
251         // For debug printing
252         virtual void PrintInfo(std::ostream &out);
253         
254         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
255
256         /*
257                 Variables
258         */
259         
260 protected:
261
262         std::ostream &m_dout;
263
264         core::map<v2s16, MapSector*> m_sectors;
265         JMutex m_sector_mutex;
266
267         v3f m_camera_position;
268         v3f m_camera_direction;
269         JMutex m_camera_mutex;
270
271         // Be sure to set this to NULL when the cached sector is deleted 
272         MapSector *m_sector_cache;
273         v2s16 m_sector_cache_p;
274
275         //WrapperHeightmap m_hwrapper;
276         
277         // Queued transforming water nodes
278         UniqueQueue<v3s16> m_transforming_liquid;
279 };
280
281 /*
282         ServerMap
283
284         This is the only map class that is able to generate map.
285 */
286
287 class ServerMap : public Map
288 {
289 public:
290         /*
291                 savedir: directory to which map data should be saved
292         */
293         ServerMap(std::string savedir);
294         ~ServerMap();
295
296         s32 mapType() const
297         {
298                 return MAPTYPE_SERVER;
299         }
300
301         /*
302                 Map generation
303         */
304         
305         // Returns the position of the chunk where the sector is in
306         v2s16 sector_to_chunk(v2s16 sectorpos)
307         {
308                 sectorpos.X += m_chunksize / 2;
309                 sectorpos.Y += m_chunksize / 2;
310                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
311                 return chunkpos;
312         }
313         
314         // Returns the position of the (0,0) sector of the chunk
315         v2s16 chunk_to_sector(v2s16 chunkpos)
316         {
317                 v2s16 sectorpos(
318                         chunkpos.X * m_chunksize,
319                         chunkpos.Y * m_chunksize
320                 );
321                 sectorpos.X -= m_chunksize / 2;
322                 sectorpos.Y -= m_chunksize / 2;
323                 return sectorpos;
324         }
325
326         /*
327                 Get a chunk.
328         */
329         MapChunk *getChunk(v2s16 chunkpos)
330         {
331                 core::map<v2s16, MapChunk*>::Node *n;
332                 n = m_chunks.find(chunkpos);
333                 if(n == NULL)
334                         return NULL;
335                 return n->getValue();
336         }
337
338         /*
339                 True if the chunk and its neighbors are fully generated.
340                 It means the chunk will not be touched in the future by the
341                 generator. If false, generateChunk will make it true.
342         */
343         bool chunkNonVolatile(v2s16 chunkpos)
344         {
345                 /*for(s16 x=-1; x<=1; x++)
346                 for(s16 y=-1; y<=1; y++)*/
347                 s16 x=0;
348                 s16 y=0;
349                 {
350                         v2s16 chunkpos0 = chunkpos + v2s16(x,y);
351                         MapChunk *chunk = getChunk(chunkpos);
352                         if(chunk == NULL)
353                                 return false;
354                         if(chunk->getGenLevel() != GENERATED_FULLY)
355                                 return false;
356                 }
357                 return true;
358         }
359
360         /*
361                 Generate a chunk.
362
363                 All chunks touching this one can be altered also.
364         */
365         MapChunk* generateChunkRaw(v2s16 chunkpos,
366                         core::map<v3s16, MapBlock*> &changed_blocks,
367                         bool force=false);
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