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