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