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