now it works nicely
[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                         bool force=false);
369         
370         /*
371                 Generate a chunk and its neighbors so that it won't be touched
372                 anymore.
373         */
374         MapChunk* generateChunk(v2s16 chunkpos,
375                         core::map<v3s16, MapBlock*> &changed_blocks);
376         
377         /*
378                 Generate a sector.
379                 
380                 This is mainly called by generateChunkRaw.
381         */
382         //ServerMapSector * generateSector(v2s16 p);
383         
384         /*
385                 Get a sector from somewhere.
386                 - Check memory
387                 - Check disk (loads blocks also)
388                 - Create blank one
389         */
390         ServerMapSector * createSector(v2s16 p);
391
392         /*
393                 Get a sector from somewhere.
394                 - Check memory
395                 - Check disk (loads blocks also)
396                 - Generate chunk
397         */
398         MapSector * emergeSector(v2s16 p,
399                         core::map<v3s16, MapBlock*> &changed_blocks);
400         
401         MapSector * emergeSector(v2s16 p)
402         {
403                 core::map<v3s16, MapBlock*> changed_blocks;
404                 return emergeSector(p, changed_blocks);
405         }
406
407         MapBlock * generateBlock(
408                         v3s16 p,
409                         MapBlock *original_dummy,
410                         ServerMapSector *sector,
411                         core::map<v3s16, MapBlock*> &changed_blocks,
412                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
413         );
414         
415         /*
416                 Get a block from somewhere.
417                 - Memory
418                 - Create blank
419         */
420         MapBlock * createBlock(v3s16 p);
421         
422         /*
423                 only_from_disk, changed_blocks and lighting_invalidated_blocks
424                 are not properly used by the new map generator.
425         */
426         MapBlock * emergeBlock(
427                         v3s16 p,
428                         bool only_from_disk,
429                         core::map<v3s16, MapBlock*> &changed_blocks,
430                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
431         );
432
433 #if 0
434         /*
435                 Forcefully get a block from somewhere.
436
437                 Exceptions:
438                 - InvalidPositionException: possible if only_from_disk==true
439                 
440                 changed_blocks:
441                 - All already existing blocks that were modified are added.
442                         - If found on disk, nothing will be added.
443                         - If generated, the new block will not be included.
444
445                 lighting_invalidated_blocks:
446                 - All blocks that have heavy-to-calculate lighting changes
447                   are added.
448                         - updateLighting() should be called for these.
449                 
450                 - A block that is in changed_blocks may not be in
451                   lighting_invalidated_blocks.
452         */
453         MapBlock * emergeBlock(
454                         v3s16 p,
455                         bool only_from_disk,
456                         core::map<v3s16, MapBlock*> &changed_blocks,
457                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
458         );
459 #endif
460
461         /*
462                 Misc. helper functions for fiddling with directory and file
463                 names when saving
464         */
465         void createDir(std::string path);
466         void createSaveDir();
467         // returns something like "xxxxxxxx"
468         std::string getSectorSubDir(v2s16 pos);
469         // returns something like "map/sectors/xxxxxxxx"
470         std::string getSectorDir(v2s16 pos);
471         std::string createSectorDir(v2s16 pos);
472         // dirname: final directory name
473         v2s16 getSectorPos(std::string dirname);
474         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
475
476         void save(bool only_changed);
477         void loadAll();
478         
479         // Saves map seed and possibly other stuff
480         void saveMapMeta();
481         void loadMapMeta();
482         
483         void saveChunkMeta();
484         void loadChunkMeta();
485         
486         // The sector mutex should be locked when calling most of these
487         
488         // This only saves sector-specific data such as the heightmap
489         // (no MapBlocks)
490         // DEPRECATED? Sectors have no metadata anymore.
491         void saveSectorMeta(ServerMapSector *sector);
492         MapSector* loadSectorMeta(std::string dirname);
493         
494         // Full load of a sector including all blocks.
495         // returns true on success, false on failure.
496         bool loadSectorFull(v2s16 p2d);
497         // If sector is not found in memory, try to load it from disk.
498         // Returns true if sector now resides in memory
499         //bool deFlushSector(v2s16 p2d);
500         
501         void saveBlock(MapBlock *block);
502         // This will generate a sector with getSector if not found.
503         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
504
505         // Gets from master heightmap
506         // DEPRECATED?
507         void getSectorCorners(v2s16 p2d, s16 *corners);
508
509         // For debug printing
510         virtual void PrintInfo(std::ostream &out);
511
512         bool isSavingEnabled(){ return m_map_saving_enabled; }
513
514 private:
515         // Seed used for all kinds of randomness
516         u64 m_seed;
517
518         std::string m_savedir;
519         bool m_map_saving_enabled;
520
521         // Chunk size in MapSectors
522         s16 m_chunksize;
523         // Chunks
524         core::map<v2s16, MapChunk*> m_chunks;
525 };
526
527 /*
528         ClientMap stuff
529 */
530
531 #ifndef SERVER
532
533 struct MapDrawControl
534 {
535         MapDrawControl():
536                 range_all(false),
537                 wanted_range(50),
538                 wanted_max_blocks(0),
539                 wanted_min_range(0),
540                 blocks_drawn(0),
541                 blocks_would_have_drawn(0)
542         {
543         }
544         // Overrides limits by drawing everything
545         bool range_all;
546         // Wanted drawing range
547         float wanted_range;
548         // Maximum number of blocks to draw
549         u32 wanted_max_blocks;
550         // Blocks in this range are drawn regardless of number of blocks drawn
551         float wanted_min_range;
552         // Number of blocks rendered is written here by the renderer
553         u32 blocks_drawn;
554         // Number of blocks that would have been drawn in wanted_range
555         u32 blocks_would_have_drawn;
556 };
557
558 class Client;
559
560 /*
561         ClientMap
562         
563         This is the only map class that is able to render itself on screen.
564 */
565
566 class ClientMap : public Map, public scene::ISceneNode
567 {
568 public:
569         ClientMap(
570                         Client *client,
571                         MapDrawControl &control,
572                         scene::ISceneNode* parent,
573                         scene::ISceneManager* mgr,
574                         s32 id
575         );
576
577         ~ClientMap();
578
579         s32 mapType() const
580         {
581                 return MAPTYPE_CLIENT;
582         }
583
584         void drop()
585         {
586                 ISceneNode::drop();
587         }
588
589         /*
590                 Forcefully get a sector from somewhere
591         */
592         MapSector * emergeSector(v2s16 p);
593
594         void deSerializeSector(v2s16 p2d, std::istream &is);
595
596         /*
597                 ISceneNode methods
598         */
599
600         virtual void OnRegisterSceneNode();
601
602         virtual void render()
603         {
604                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
605                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
606                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
607         }
608         
609         virtual const core::aabbox3d<f32>& getBoundingBox() const
610         {
611                 return m_box;
612         }
613
614         void renderMap(video::IVideoDriver* driver, s32 pass);
615
616         /*
617                 Methods for setting temporary modifications to nodes for
618                 drawing.
619
620                 Returns true if something changed.
621                 
622                 All blocks whose mesh could have been changed are inserted
623                 to affected_blocks.
624         */
625         bool setTempMod(v3s16 p, NodeMod mod,
626                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
627         bool clearTempMod(v3s16 p,
628                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
629         // Efficient implementation needs a cache of TempMods
630         //void clearTempMods();
631
632         // For debug printing
633         virtual void PrintInfo(std::ostream &out);
634         
635 private:
636         Client *m_client;
637         
638         core::aabbox3d<f32> m_box;
639         
640         // This is the master heightmap mesh
641         //scene::SMesh *mesh;
642         //JMutex mesh_mutex;
643         
644         MapDrawControl &m_control;
645 };
646
647 #endif
648
649 class MapVoxelManipulator : public VoxelManipulator
650 {
651 public:
652         MapVoxelManipulator(Map *map);
653         virtual ~MapVoxelManipulator();
654         
655         virtual void clear()
656         {
657                 VoxelManipulator::clear();
658                 m_loaded_blocks.clear();
659         }
660
661         virtual void emerge(VoxelArea a, s32 caller_id=-1);
662
663         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
664
665 protected:
666         Map *m_map;
667         /*
668                 key = blockpos
669                 value = block existed when loaded
670         */
671         core::map<v3s16, bool> m_loaded_blocks;
672 };
673
674 class ManualMapVoxelManipulator : public MapVoxelManipulator
675 {
676 public:
677         ManualMapVoxelManipulator(Map *map);
678         virtual ~ManualMapVoxelManipulator();
679         
680         virtual void emerge(VoxelArea a, s32 caller_id=-1);
681
682         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
683         
684         // This is much faster with big chunks of generated data
685         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
686
687 protected:
688         bool m_create_area;
689 };
690
691 #endif
692