]> git.lizzy.rs Git - minetest.git/blob - src/map.h
b3ef47282be07617b4a431c7ec0df8ee950f92cd
[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         // TODO
479         void saveMapMeta();
480         void loadMapMeta();
481         
482         // TODO
483         void saveChunkMeta();
484         void loadChunkMeta();
485         
486         // DEPRECATED
487         void saveMasterHeightmap();
488         void loadMasterHeightmap();
489
490         // The sector mutex should be locked when calling most of these
491         
492         // This only saves sector-specific data such as the heightmap
493         // (no MapBlocks)
494         // DEPRECATED? Sectors have no metadata anymore.
495         void saveSectorMeta(ServerMapSector *sector);
496         MapSector* loadSectorMeta(std::string dirname);
497         
498         // Full load of a sector including all blocks.
499         // returns true on success, false on failure.
500         bool loadSectorFull(v2s16 p2d);
501         // If sector is not found in memory, try to load it from disk.
502         // Returns true if sector now resides in memory
503         //bool deFlushSector(v2s16 p2d);
504         
505         void saveBlock(MapBlock *block);
506         // This will generate a sector with getSector if not found.
507         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
508
509         // Gets from master heightmap
510         // DEPRECATED?
511         void getSectorCorners(v2s16 p2d, s16 *corners);
512
513         // For debug printing
514         virtual void PrintInfo(std::ostream &out);
515
516 private:
517         // Seed used for all kinds of randomness
518         u64 m_seed;
519
520         std::string m_savedir;
521         bool m_map_saving_enabled;
522
523         // Chunk size in MapSectors
524         s16 m_chunksize;
525         // Chunks
526         core::map<v2s16, MapChunk*> m_chunks;
527 };
528
529 /*
530         ClientMap stuff
531 */
532
533 #ifndef SERVER
534
535 struct MapDrawControl
536 {
537         MapDrawControl():
538                 range_all(false),
539                 wanted_range(50),
540                 wanted_max_blocks(0),
541                 wanted_min_range(0),
542                 blocks_drawn(0),
543                 blocks_would_have_drawn(0)
544         {
545         }
546         // Overrides limits by drawing everything
547         bool range_all;
548         // Wanted drawing range
549         float wanted_range;
550         // Maximum number of blocks to draw
551         u32 wanted_max_blocks;
552         // Blocks in this range are drawn regardless of number of blocks drawn
553         float wanted_min_range;
554         // Number of blocks rendered is written here by the renderer
555         u32 blocks_drawn;
556         // Number of blocks that would have been drawn in wanted_range
557         u32 blocks_would_have_drawn;
558 };
559
560 class Client;
561
562 /*
563         ClientMap
564         
565         This is the only map class that is able to render itself on screen.
566 */
567
568 class ClientMap : public Map, public scene::ISceneNode
569 {
570 public:
571         ClientMap(
572                         Client *client,
573                         MapDrawControl &control,
574                         scene::ISceneNode* parent,
575                         scene::ISceneManager* mgr,
576                         s32 id
577         );
578
579         ~ClientMap();
580
581         s32 mapType() const
582         {
583                 return MAPTYPE_CLIENT;
584         }
585
586         void drop()
587         {
588                 ISceneNode::drop();
589         }
590
591         /*
592                 Forcefully get a sector from somewhere
593         */
594         MapSector * emergeSector(v2s16 p);
595
596         void deSerializeSector(v2s16 p2d, std::istream &is);
597
598         /*
599                 ISceneNode methods
600         */
601
602         virtual void OnRegisterSceneNode();
603
604         virtual void render()
605         {
606                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
607                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
608                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
609         }
610         
611         virtual const core::aabbox3d<f32>& getBoundingBox() const
612         {
613                 return m_box;
614         }
615
616         void renderMap(video::IVideoDriver* driver, s32 pass);
617
618         /*
619                 Methods for setting temporary modifications to nodes for
620                 drawing.
621
622                 Returns true if something changed.
623                 
624                 All blocks whose mesh could have been changed are inserted
625                 to affected_blocks.
626         */
627         bool setTempMod(v3s16 p, NodeMod mod,
628                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
629         bool clearTempMod(v3s16 p,
630                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
631         // Efficient implementation needs a cache of TempMods
632         //void clearTempMods();
633
634         // For debug printing
635         virtual void PrintInfo(std::ostream &out);
636         
637 private:
638         Client *m_client;
639         
640         core::aabbox3d<f32> m_box;
641         
642         // This is the master heightmap mesh
643         //scene::SMesh *mesh;
644         //JMutex mesh_mutex;
645         
646         MapDrawControl &m_control;
647 };
648
649 #endif
650
651 class MapVoxelManipulator : public VoxelManipulator
652 {
653 public:
654         MapVoxelManipulator(Map *map);
655         virtual ~MapVoxelManipulator();
656         
657         virtual void clear()
658         {
659                 VoxelManipulator::clear();
660                 m_loaded_blocks.clear();
661         }
662
663         virtual void emerge(VoxelArea a, s32 caller_id=-1);
664
665         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
666
667 protected:
668         Map *m_map;
669         /*
670                 key = blockpos
671                 value = block existed when loaded
672         */
673         core::map<v3s16, bool> m_loaded_blocks;
674 };
675
676 class ManualMapVoxelManipulator : public MapVoxelManipulator
677 {
678 public:
679         ManualMapVoxelManipulator(Map *map);
680         virtual ~ManualMapVoxelManipulator();
681         
682         virtual void emerge(VoxelArea a, s32 caller_id=-1);
683
684         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
685         
686         // This is much faster with big chunks of generated data
687         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
688
689 protected:
690         bool m_create_area;
691 };
692
693 #endif
694