]> git.lizzy.rs Git - dragonfireclient.git/blob - src/map.h
mapgen work-in-progress
[dragonfireclient.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
43 /*
44         Some exposed functions
45 */
46
47 double base_rock_level_2d(u64 seed, v2f p);
48 bool get_have_sand_coast(u64 seed, v2f p);
49 bool get_have_sand_ground(u64 seed, v2f p);
50 double get_turbulence_factor_2d(u64 seed, v2f p);
51
52 /*
53 */
54
55 #define MAPTYPE_BASE 0
56 #define MAPTYPE_SERVER 1
57 #define MAPTYPE_CLIENT 2
58
59 enum MapEditEventType{
60         MEET_ADDNODE,
61         MEET_REMOVENODE,
62         MEET_OTHER
63 };
64
65 struct MapEditEvent
66 {
67         MapEditEventType type;
68         v3s16 p;
69         MapNode n;
70         core::map<v3s16, bool> modified_blocks;
71         u16 already_known_by_peer;
72
73         MapEditEvent():
74                 type(MEET_OTHER),
75                 already_known_by_peer(0)
76         {
77         }
78         
79         MapEditEvent * clone()
80         {
81                 MapEditEvent *event = new MapEditEvent();
82                 event->type = type;
83                 event->p = p;
84                 event->n = n;
85                 for(core::map<v3s16, bool>::Iterator
86                                 i = modified_blocks.getIterator();
87                                 i.atEnd()==false; i++)
88                 {
89                         v3s16 p = i.getNode()->getKey();
90                         bool v = i.getNode()->getValue();
91                         event->modified_blocks.insert(p, v);
92                 }
93                 return event;
94         }
95 };
96
97 class MapEventReceiver
98 {
99 public:
100         // event shall be deleted by caller after the call.
101         virtual void onMapEditEvent(MapEditEvent *event) = 0;
102 };
103
104 class Map : public NodeContainer
105 {
106 public:
107
108         Map(std::ostream &dout);
109         virtual ~Map();
110
111         virtual u16 nodeContainerId() const
112         {
113                 return NODECONTAINER_ID_MAP;
114         }
115
116         virtual s32 mapType() const
117         {
118                 return MAPTYPE_BASE;
119         }
120         
121         /*
122                 Drop (client) or delete (server) the map.
123         */
124         virtual void drop()
125         {
126                 delete this;
127         }
128
129         void addEventReceiver(MapEventReceiver *event_receiver);
130         void removeEventReceiver(MapEventReceiver *event_receiver);
131         // event shall be deleted by caller after the call.
132         void dispatchEvent(MapEditEvent *event);
133
134         // On failure returns NULL
135         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
136         // On failure returns NULL
137         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
138         // On failure throws InvalidPositionException
139         MapSector * getSectorNoGenerate(v2s16 p2d);
140         // Gets an existing sector or creates an empty one
141         //MapSector * getSectorCreate(v2s16 p2d);
142
143         /*
144                 This is overloaded by ClientMap and ServerMap to allow
145                 their differing fetch methods.
146         */
147         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
148         virtual MapSector * emergeSector(v2s16 p,
149                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
150
151         // Returns InvalidPositionException if not found
152         MapBlock * getBlockNoCreate(v3s16 p);
153         // Returns NULL if not found
154         MapBlock * getBlockNoCreateNoEx(v3s16 p);
155         // Gets an existing block or creates an empty one
156         //MapBlock * getBlockCreate(v3s16 p);
157         
158         // Returns InvalidPositionException if not found
159         bool isNodeUnderground(v3s16 p);
160         
161         // virtual from NodeContainer
162         bool isValidPosition(v3s16 p)
163         {
164                 v3s16 blockpos = getNodeBlockPos(p);
165                 MapBlock *blockref;
166                 try{
167                         blockref = getBlockNoCreate(blockpos);
168                 }
169                 catch(InvalidPositionException &e)
170                 {
171                         return false;
172                 }
173                 return true;
174                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
175                 bool is_valid = blockref->isValidPosition(relpos);
176                 return is_valid;*/
177         }
178         
179         // virtual from NodeContainer
180         // throws InvalidPositionException if not found
181         MapNode getNode(v3s16 p)
182         {
183                 v3s16 blockpos = getNodeBlockPos(p);
184                 MapBlock * blockref = getBlockNoCreate(blockpos);
185                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
186
187                 return blockref->getNodeNoCheck(relpos);
188         }
189
190         // virtual from NodeContainer
191         // throws InvalidPositionException if not found
192         void setNode(v3s16 p, MapNode & n)
193         {
194                 v3s16 blockpos = getNodeBlockPos(p);
195                 MapBlock * blockref = getBlockNoCreate(blockpos);
196                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
197                 blockref->setNodeNoCheck(relpos, n);
198         }
199         
200         // Returns a CONTENT_IGNORE node if not found
201         MapNode getNodeNoEx(v3s16 p)
202         {
203                 try{
204                         v3s16 blockpos = getNodeBlockPos(p);
205                         MapBlock * blockref = getBlockNoCreate(blockpos);
206                         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
207
208                         return blockref->getNodeNoCheck(relpos);
209                 }
210                 catch(InvalidPositionException &e)
211                 {
212                         return MapNode(CONTENT_IGNORE);
213                 }
214         }
215
216         void unspreadLight(enum LightBank bank,
217                         core::map<v3s16, u8> & from_nodes,
218                         core::map<v3s16, bool> & light_sources,
219                         core::map<v3s16, MapBlock*> & modified_blocks);
220
221         void unLightNeighbors(enum LightBank bank,
222                         v3s16 pos, u8 lightwas,
223                         core::map<v3s16, bool> & light_sources,
224                         core::map<v3s16, MapBlock*> & modified_blocks);
225         
226         void spreadLight(enum LightBank bank,
227                         core::map<v3s16, bool> & from_nodes,
228                         core::map<v3s16, MapBlock*> & modified_blocks);
229         
230         void lightNeighbors(enum LightBank bank,
231                         v3s16 pos,
232                         core::map<v3s16, MapBlock*> & modified_blocks);
233
234         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
235
236         s16 propagateSunlight(v3s16 start,
237                         core::map<v3s16, MapBlock*> & modified_blocks);
238         
239         void updateLighting(enum LightBank bank,
240                         core::map<v3s16, MapBlock*>  & a_blocks,
241                         core::map<v3s16, MapBlock*> & modified_blocks);
242                         
243         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
244                         core::map<v3s16, MapBlock*> & modified_blocks);
245                         
246         /*
247                 These handle lighting but not faces.
248         */
249         void addNodeAndUpdate(v3s16 p, MapNode n,
250                         core::map<v3s16, MapBlock*> &modified_blocks);
251         void removeNodeAndUpdate(v3s16 p,
252                         core::map<v3s16, MapBlock*> &modified_blocks);
253
254         /*
255                 Wrappers for the latter ones.
256                 These emit events.
257                 Return true if succeeded, false if not.
258         */
259         bool addNodeWithEvent(v3s16 p, MapNode n);
260         bool removeNodeWithEvent(v3s16 p);
261         
262         /*
263                 Takes the blocks at the edges into account
264         */
265         bool dayNightDiffed(v3s16 blockpos);
266
267         //core::aabbox3d<s16> getDisplayedBlockArea();
268
269         //bool updateChangedVisibleArea();
270         
271         virtual void save(bool only_changed){assert(0);};
272
273         /*
274                 Updates usage timers
275         */
276         void timerUpdate(float dtime);
277         
278         // Takes cache into account
279         // sector mutex should be locked when calling
280         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
281         
282         // Returns count of deleted sectors
283         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
284                         core::list<v3s16> *deleted_blocks=NULL);
285
286         // For debug printing
287         virtual void PrintInfo(std::ostream &out);
288         
289         void transformLiquids(core::map<v3s16, MapBlock*> & modified_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         u64 getSeed(){ return m_seed; }
547
548 private:
549         // Seed used for all kinds of randomness
550         u64 m_seed;
551
552         std::string m_savedir;
553         bool m_map_saving_enabled;
554
555         // Chunk size in MapSectors
556         s16 m_chunksize;
557         // Chunks
558         core::map<v2s16, MapChunk*> m_chunks;
559 };
560
561 /*
562         ClientMap stuff
563 */
564
565 #ifndef SERVER
566
567 struct MapDrawControl
568 {
569         MapDrawControl():
570                 range_all(false),
571                 wanted_range(50),
572                 wanted_max_blocks(0),
573                 wanted_min_range(0),
574                 blocks_drawn(0),
575                 blocks_would_have_drawn(0)
576         {
577         }
578         // Overrides limits by drawing everything
579         bool range_all;
580         // Wanted drawing range
581         float wanted_range;
582         // Maximum number of blocks to draw
583         u32 wanted_max_blocks;
584         // Blocks in this range are drawn regardless of number of blocks drawn
585         float wanted_min_range;
586         // Number of blocks rendered is written here by the renderer
587         u32 blocks_drawn;
588         // Number of blocks that would have been drawn in wanted_range
589         u32 blocks_would_have_drawn;
590 };
591
592 class Client;
593
594 /*
595         ClientMap
596         
597         This is the only map class that is able to render itself on screen.
598 */
599
600 class ClientMap : public Map, public scene::ISceneNode
601 {
602 public:
603         ClientMap(
604                         Client *client,
605                         MapDrawControl &control,
606                         scene::ISceneNode* parent,
607                         scene::ISceneManager* mgr,
608                         s32 id
609         );
610
611         ~ClientMap();
612
613         s32 mapType() const
614         {
615                 return MAPTYPE_CLIENT;
616         }
617
618         void drop()
619         {
620                 ISceneNode::drop();
621         }
622
623         void updateCamera(v3f pos, v3f dir)
624         {
625                 JMutexAutoLock lock(m_camera_mutex);
626                 m_camera_position = pos;
627                 m_camera_direction = dir;
628         }
629
630         /*
631                 Forcefully get a sector from somewhere
632         */
633         MapSector * emergeSector(v2s16 p);
634
635         void deSerializeSector(v2s16 p2d, std::istream &is);
636
637         /*
638                 ISceneNode methods
639         */
640
641         virtual void OnRegisterSceneNode();
642
643         virtual void render()
644         {
645                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
646                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
647                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
648         }
649         
650         virtual const core::aabbox3d<f32>& getBoundingBox() const
651         {
652                 return m_box;
653         }
654
655         void renderMap(video::IVideoDriver* driver, s32 pass);
656
657         /*
658                 Methods for setting temporary modifications to nodes for
659                 drawing.
660
661                 Returns true if something changed.
662                 
663                 All blocks whose mesh could have been changed are inserted
664                 to affected_blocks.
665         */
666         bool setTempMod(v3s16 p, NodeMod mod,
667                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
668         bool clearTempMod(v3s16 p,
669                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
670         // Efficient implementation needs a cache of TempMods
671         //void clearTempMods();
672
673         void expireMeshes(bool only_daynight_diffed);
674         
675         /*
676                 Update the faces of the given block and blocks on the
677                 leading edge.
678         */
679         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
680         
681         // Update meshes that touch the node
682         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
683
684         // For debug printing
685         virtual void PrintInfo(std::ostream &out);
686         
687 private:
688         Client *m_client;
689         
690         core::aabbox3d<f32> m_box;
691         
692         // This is the master heightmap mesh
693         //scene::SMesh *mesh;
694         //JMutex mesh_mutex;
695         
696         MapDrawControl &m_control;
697
698         v3f m_camera_position;
699         v3f m_camera_direction;
700         JMutex m_camera_mutex;
701
702 };
703
704 #endif
705
706 class MapVoxelManipulator : public VoxelManipulator
707 {
708 public:
709         MapVoxelManipulator(Map *map);
710         virtual ~MapVoxelManipulator();
711         
712         virtual void clear()
713         {
714                 VoxelManipulator::clear();
715                 m_loaded_blocks.clear();
716         }
717
718         virtual void emerge(VoxelArea a, s32 caller_id=-1);
719
720         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
721
722 protected:
723         Map *m_map;
724         /*
725                 key = blockpos
726                 value = block existed when loaded
727         */
728         core::map<v3s16, bool> m_loaded_blocks;
729 };
730
731 class ManualMapVoxelManipulator : public MapVoxelManipulator
732 {
733 public:
734         ManualMapVoxelManipulator(Map *map);
735         virtual ~ManualMapVoxelManipulator();
736         
737         virtual void emerge(VoxelArea a, s32 caller_id=-1);
738
739         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
740         
741         // This is much faster with big chunks of generated data
742         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
743
744 protected:
745         bool m_create_area;
746 };
747
748 #endif
749