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