]> git.lizzy.rs Git - dragonfireclient.git/blob - src/map.h
mapgen tweaking
[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(u64 seed, v2f p);
49
50 /*
51 */
52
53 #define MAPTYPE_BASE 0
54 #define MAPTYPE_SERVER 1
55 #define MAPTYPE_CLIENT 2
56
57 enum MapEditEventType{
58         MEET_ADDNODE,
59         MEET_REMOVENODE,
60         MEET_OTHER
61 };
62
63 struct MapEditEvent
64 {
65         MapEditEventType type;
66         v3s16 p;
67         MapNode n;
68         core::map<v3s16, bool> modified_blocks;
69         u16 already_known_by_peer;
70
71         MapEditEvent():
72                 type(MEET_OTHER),
73                 already_known_by_peer(0)
74         {
75         }
76         
77         MapEditEvent * clone()
78         {
79                 MapEditEvent *event = new MapEditEvent();
80                 event->type = type;
81                 event->p = p;
82                 event->n = n;
83                 for(core::map<v3s16, bool>::Iterator
84                                 i = modified_blocks.getIterator();
85                                 i.atEnd()==false; i++)
86                 {
87                         v3s16 p = i.getNode()->getKey();
88                         bool v = i.getNode()->getValue();
89                         event->modified_blocks.insert(p, v);
90                 }
91                 return event;
92         }
93 };
94
95 class MapEventReceiver
96 {
97 public:
98         // event shall be deleted by caller after the call.
99         virtual void onMapEditEvent(MapEditEvent *event) = 0;
100 };
101
102 class Map : public NodeContainer
103 {
104 public:
105
106         Map(std::ostream &dout);
107         virtual ~Map();
108
109         virtual u16 nodeContainerId() const
110         {
111                 return NODECONTAINER_ID_MAP;
112         }
113
114         virtual s32 mapType() const
115         {
116                 return MAPTYPE_BASE;
117         }
118         
119         /*
120                 Drop (client) or delete (server) the map.
121         */
122         virtual void drop()
123         {
124                 delete this;
125         }
126
127         void addEventReceiver(MapEventReceiver *event_receiver);
128         void removeEventReceiver(MapEventReceiver *event_receiver);
129         // event shall be deleted by caller after the call.
130         void dispatchEvent(MapEditEvent *event);
131
132         // On failure returns NULL
133         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
134         // On failure returns NULL
135         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
136         // On failure throws InvalidPositionException
137         MapSector * getSectorNoGenerate(v2s16 p2d);
138         // Gets an existing sector or creates an empty one
139         //MapSector * getSectorCreate(v2s16 p2d);
140
141         /*
142                 This is overloaded by ClientMap and ServerMap to allow
143                 their differing fetch methods.
144         */
145         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
146         virtual MapSector * emergeSector(v2s16 p,
147                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
148
149         // Returns InvalidPositionException if not found
150         MapBlock * getBlockNoCreate(v3s16 p);
151         // Returns NULL if not found
152         MapBlock * getBlockNoCreateNoEx(v3s16 p);
153         // Gets an existing block or creates an empty one
154         //MapBlock * getBlockCreate(v3s16 p);
155         
156         // Returns InvalidPositionException if not found
157         bool isNodeUnderground(v3s16 p);
158         
159         // virtual from NodeContainer
160         bool isValidPosition(v3s16 p)
161         {
162                 v3s16 blockpos = getNodeBlockPos(p);
163                 MapBlock *blockref;
164                 try{
165                         blockref = getBlockNoCreate(blockpos);
166                 }
167                 catch(InvalidPositionException &e)
168                 {
169                         return false;
170                 }
171                 return true;
172                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
173                 bool is_valid = blockref->isValidPosition(relpos);
174                 return is_valid;*/
175         }
176         
177         // virtual from NodeContainer
178         // throws InvalidPositionException if not found
179         MapNode getNode(v3s16 p)
180         {
181                 v3s16 blockpos = getNodeBlockPos(p);
182                 MapBlock * blockref = getBlockNoCreate(blockpos);
183                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
184
185                 return blockref->getNodeNoCheck(relpos);
186         }
187
188         // virtual from NodeContainer
189         // throws InvalidPositionException if not found
190         void setNode(v3s16 p, MapNode & n)
191         {
192                 v3s16 blockpos = getNodeBlockPos(p);
193                 MapBlock * blockref = getBlockNoCreate(blockpos);
194                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
195                 blockref->setNodeNoCheck(relpos, n);
196         }
197         
198         // Returns a CONTENT_IGNORE node if not found
199         MapNode getNodeNoEx(v3s16 p)
200         {
201                 try{
202                         v3s16 blockpos = getNodeBlockPos(p);
203                         MapBlock * blockref = getBlockNoCreate(blockpos);
204                         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
205
206                         return blockref->getNodeNoCheck(relpos);
207                 }
208                 catch(InvalidPositionException &e)
209                 {
210                         return MapNode(CONTENT_IGNORE);
211                 }
212         }
213
214         void unspreadLight(enum LightBank bank,
215                         core::map<v3s16, u8> & from_nodes,
216                         core::map<v3s16, bool> & light_sources,
217                         core::map<v3s16, MapBlock*> & modified_blocks);
218
219         void unLightNeighbors(enum LightBank bank,
220                         v3s16 pos, u8 lightwas,
221                         core::map<v3s16, bool> & light_sources,
222                         core::map<v3s16, MapBlock*> & modified_blocks);
223         
224         void spreadLight(enum LightBank bank,
225                         core::map<v3s16, bool> & from_nodes,
226                         core::map<v3s16, MapBlock*> & modified_blocks);
227         
228         void lightNeighbors(enum LightBank bank,
229                         v3s16 pos,
230                         core::map<v3s16, MapBlock*> & modified_blocks);
231
232         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
233
234         s16 propagateSunlight(v3s16 start,
235                         core::map<v3s16, MapBlock*> & modified_blocks);
236         
237         void updateLighting(enum LightBank bank,
238                         core::map<v3s16, MapBlock*>  & a_blocks,
239                         core::map<v3s16, MapBlock*> & modified_blocks);
240                         
241         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
242                         core::map<v3s16, MapBlock*> & modified_blocks);
243                         
244         /*
245                 These handle lighting but not faces.
246         */
247         void addNodeAndUpdate(v3s16 p, MapNode n,
248                         core::map<v3s16, MapBlock*> &modified_blocks);
249         void removeNodeAndUpdate(v3s16 p,
250                         core::map<v3s16, MapBlock*> &modified_blocks);
251
252         /*
253                 Wrappers for the latter ones.
254                 These emit events.
255                 Return true if succeeded, false if not.
256         */
257         bool addNodeWithEvent(v3s16 p, MapNode n);
258         bool removeNodeWithEvent(v3s16 p);
259         
260         /*
261                 Takes the blocks at the edges into account
262         */
263         bool dayNightDiffed(v3s16 blockpos);
264
265         //core::aabbox3d<s16> getDisplayedBlockArea();
266
267         //bool updateChangedVisibleArea();
268         
269         virtual void save(bool only_changed){assert(0);};
270
271         /*
272                 Updates usage timers
273         */
274         void timerUpdate(float dtime);
275         
276         // Takes cache into account
277         // sector mutex should be locked when calling
278         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
279         
280         // Returns count of deleted sectors
281         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
282                         core::list<v3s16> *deleted_blocks=NULL);
283
284         // For debug printing
285         virtual void PrintInfo(std::ostream &out);
286         
287         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
288
289         /*
290                 Variables
291         */
292         
293 protected:
294
295         std::ostream &m_dout;
296
297         core::map<MapEventReceiver*, bool> m_event_receivers;
298         
299         // Mutex is important because on client map is accessed asynchronously
300         core::map<v2s16, MapSector*> m_sectors;
301         JMutex m_sector_mutex;
302
303         // Be sure to set this to NULL when the cached sector is deleted 
304         MapSector *m_sector_cache;
305         v2s16 m_sector_cache_p;
306
307         //WrapperHeightmap m_hwrapper;
308         
309         // Queued transforming water nodes
310         UniqueQueue<v3s16> m_transforming_liquid;
311 };
312
313 /*
314         ServerMap
315
316         This is the only map class that is able to generate map.
317 */
318
319 class ServerMap : public Map
320 {
321 public:
322         /*
323                 savedir: directory to which map data should be saved
324         */
325         ServerMap(std::string savedir);
326         ~ServerMap();
327
328         s32 mapType() const
329         {
330                 return MAPTYPE_SERVER;
331         }
332
333         /*
334                 Map generation
335         */
336         
337         // Returns the position of the chunk where the sector is in
338         v2s16 sector_to_chunk(v2s16 sectorpos)
339         {
340                 sectorpos.X += m_chunksize / 2;
341                 sectorpos.Y += m_chunksize / 2;
342                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
343                 return chunkpos;
344         }
345         
346         // Returns the position of the (0,0) sector of the chunk
347         v2s16 chunk_to_sector(v2s16 chunkpos)
348         {
349                 v2s16 sectorpos(
350                         chunkpos.X * m_chunksize,
351                         chunkpos.Y * m_chunksize
352                 );
353                 sectorpos.X -= m_chunksize / 2;
354                 sectorpos.Y -= m_chunksize / 2;
355                 return sectorpos;
356         }
357
358         /*
359                 Get a chunk.
360         */
361         MapChunk *getChunk(v2s16 chunkpos)
362         {
363                 core::map<v2s16, MapChunk*>::Node *n;
364                 n = m_chunks.find(chunkpos);
365                 if(n == NULL)
366                         return NULL;
367                 return n->getValue();
368         }
369
370         /*
371                 True if the chunk and its neighbors are fully generated.
372                 It means the chunk will not be touched in the future by the
373                 generator. If false, generateChunk will make it true.
374         */
375         bool chunkNonVolatile(v2s16 chunkpos)
376         {
377                 /*for(s16 x=-1; x<=1; x++)
378                 for(s16 y=-1; y<=1; y++)*/
379                 s16 x=0;
380                 s16 y=0;
381                 {
382                         v2s16 chunkpos0 = chunkpos + v2s16(x,y);
383                         MapChunk *chunk = getChunk(chunkpos);
384                         if(chunk == NULL)
385                                 return false;
386                         if(chunk->getGenLevel() != GENERATED_FULLY)
387                                 return false;
388                 }
389                 return true;
390         }
391
392         /*
393                 Generate a chunk.
394
395                 All chunks touching this one can be altered also.
396         */
397         MapChunk* generateChunkRaw(v2s16 chunkpos,
398                         core::map<v3s16, MapBlock*> &changed_blocks,
399                         bool force=false);
400         
401         /*
402                 Generate a chunk and its neighbors so that it won't be touched
403                 anymore.
404         */
405         MapChunk* generateChunk(v2s16 chunkpos,
406                         core::map<v3s16, MapBlock*> &changed_blocks);
407         
408         /*
409                 Generate a sector.
410                 
411                 This is mainly called by generateChunkRaw.
412         */
413         //ServerMapSector * generateSector(v2s16 p);
414         
415         /*
416                 Get a sector from somewhere.
417                 - Check memory
418                 - Check disk (loads blocks also)
419                 - Create blank one
420         */
421         ServerMapSector * createSector(v2s16 p);
422
423         /*
424                 Get a sector from somewhere.
425                 - Check memory
426                 - Check disk (loads blocks also)
427                 - Generate chunk
428         */
429         MapSector * emergeSector(v2s16 p,
430                         core::map<v3s16, MapBlock*> &changed_blocks);
431         
432         MapSector * emergeSector(v2s16 p)
433         {
434                 core::map<v3s16, MapBlock*> changed_blocks;
435                 return emergeSector(p, changed_blocks);
436         }
437
438         MapBlock * generateBlock(
439                         v3s16 p,
440                         MapBlock *original_dummy,
441                         ServerMapSector *sector,
442                         core::map<v3s16, MapBlock*> &changed_blocks,
443                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
444         );
445         
446         /*
447                 Get a block from somewhere.
448                 - Memory
449                 - Create blank
450         */
451         MapBlock * createBlock(v3s16 p);
452         
453         /*
454                 only_from_disk, changed_blocks and lighting_invalidated_blocks
455                 are not properly used by the new map generator.
456         */
457         MapBlock * emergeBlock(
458                         v3s16 p,
459                         bool only_from_disk,
460                         core::map<v3s16, MapBlock*> &changed_blocks,
461                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
462         );
463
464 #if 0
465         /*
466                 Forcefully get a block from somewhere.
467
468                 Exceptions:
469                 - InvalidPositionException: possible if only_from_disk==true
470                 
471                 changed_blocks:
472                 - All already existing blocks that were modified are added.
473                         - If found on disk, nothing will be added.
474                         - If generated, the new block will not be included.
475
476                 lighting_invalidated_blocks:
477                 - All blocks that have heavy-to-calculate lighting changes
478                   are added.
479                         - updateLighting() should be called for these.
480                 
481                 - A block that is in changed_blocks may not be in
482                   lighting_invalidated_blocks.
483         */
484         MapBlock * emergeBlock(
485                         v3s16 p,
486                         bool only_from_disk,
487                         core::map<v3s16, MapBlock*> &changed_blocks,
488                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
489         );
490 #endif
491         
492         // Helper for placing objects on ground level
493         s16 findGroundLevel(v2s16 p2d);
494
495         /*
496                 Misc. helper functions for fiddling with directory and file
497                 names when saving
498         */
499         void createDir(std::string path);
500         void createSaveDir();
501         // returns something like "xxxxxxxx"
502         std::string getSectorSubDir(v2s16 pos);
503         // returns something like "map/sectors/xxxxxxxx"
504         std::string getSectorDir(v2s16 pos);
505         std::string createSectorDir(v2s16 pos);
506         // dirname: final directory name
507         v2s16 getSectorPos(std::string dirname);
508         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
509
510         void save(bool only_changed);
511         void loadAll();
512         
513         // Saves map seed and possibly other stuff
514         void saveMapMeta();
515         void loadMapMeta();
516         
517         void saveChunkMeta();
518         void loadChunkMeta();
519         
520         // The sector mutex should be locked when calling most of these
521         
522         // This only saves sector-specific data such as the heightmap
523         // (no MapBlocks)
524         // DEPRECATED? Sectors have no metadata anymore.
525         void saveSectorMeta(ServerMapSector *sector);
526         MapSector* loadSectorMeta(std::string dirname);
527         
528         // Full load of a sector including all blocks.
529         // returns true on success, false on failure.
530         bool loadSectorFull(v2s16 p2d);
531         // If sector is not found in memory, try to load it from disk.
532         // Returns true if sector now resides in memory
533         //bool deFlushSector(v2s16 p2d);
534         
535         void saveBlock(MapBlock *block);
536         // This will generate a sector with getSector if not found.
537         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
538
539         // For debug printing
540         virtual void PrintInfo(std::ostream &out);
541
542         bool isSavingEnabled(){ return m_map_saving_enabled; }
543
544         u64 getSeed(){ return m_seed; }
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         virtual void emerge(VoxelArea a, s32 caller_id=-1);
736
737         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
738         
739         // This is much faster with big chunks of generated data
740         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
741
742 protected:
743         bool m_create_area;
744 };
745
746 #endif
747