Initial commit of mapgen v.2. Lacks configuration and saving to disk.
[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
44 class CacheLock
45 {
46 public:
47         CacheLock()
48         {
49                 m_count = 0;
50                 m_count_mutex.Init();
51                 m_cache_mutex.Init();
52                 m_waitcache_mutex.Init();
53         }
54
55         void cacheCreated()
56         {
57                 //dstream<<"cacheCreated() begin"<<std::endl;
58                 JMutexAutoLock waitcachelock(m_waitcache_mutex);
59                 JMutexAutoLock countlock(m_count_mutex);
60
61                 // If this is the first cache, grab the cache lock
62                 if(m_count == 0)
63                         m_cache_mutex.Lock();
64                         
65                 m_count++;
66
67                 //dstream<<"cacheCreated() end"<<std::endl;
68         }
69
70         void cacheRemoved()
71         {
72                 //dstream<<"cacheRemoved() begin"<<std::endl;
73                 JMutexAutoLock countlock(m_count_mutex);
74
75                 assert(m_count > 0);
76
77                 m_count--;
78                 
79                 // If this is the last one, release the cache lock
80                 if(m_count == 0)
81                         m_cache_mutex.Unlock();
82
83                 //dstream<<"cacheRemoved() end"<<std::endl;
84         }
85
86         /*
87                 This lock should be taken when removing stuff that can be
88                 pointed by the cache.
89
90                 You'll want to grab this in a SharedPtr.
91         */
92         JMutexAutoLock * waitCaches()
93         {
94                 //dstream<<"waitCaches() begin"<<std::endl;
95                 JMutexAutoLock waitcachelock(m_waitcache_mutex);
96                 JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
97                 //dstream<<"waitCaches() end"<<std::endl;
98                 return lock;
99         }
100
101 private:
102         // Count of existing caches
103         u32 m_count;
104         JMutex m_count_mutex;
105         // This is locked always when there are some caches
106         JMutex m_cache_mutex;
107         // Locked so that when waitCaches() is called, no more caches are created
108         JMutex m_waitcache_mutex;
109 };
110
111 #define MAPTYPE_BASE 0
112 #define MAPTYPE_SERVER 1
113 #define MAPTYPE_CLIENT 2
114
115 class Map : public NodeContainer, public Heightmappish
116 {
117 protected:
118
119         std::ostream &m_dout;
120
121         core::map<v2s16, MapSector*> m_sectors;
122         JMutex m_sector_mutex;
123
124         v3f m_camera_position;
125         v3f m_camera_direction;
126         JMutex m_camera_mutex;
127
128         // Be sure to set this to NULL when the cached sector is deleted 
129         MapSector *m_sector_cache;
130         v2s16 m_sector_cache_p;
131
132         WrapperHeightmap m_hwrapper;
133
134 public:
135
136         v3s16 drawoffset; // for drawbox()
137         
138         /*
139                 Used by MapBlockPointerCache.
140
141                 waitCaches() can be called to remove all caches before continuing
142
143                 TODO: Remove this, MapBlockPointerCache doesn't exist anymore,
144                       because it doesn't give any speed benefits
145         */
146         CacheLock m_blockcachelock;
147
148         Map(std::ostream &dout);
149         virtual ~Map();
150
151         virtual u16 nodeContainerId() const
152         {
153                 return NODECONTAINER_ID_MAP;
154         }
155
156         virtual s32 mapType() const
157         {
158                 return MAPTYPE_BASE;
159         }
160
161         virtual void drop()
162         {
163                 delete this;
164         }
165
166         void updateCamera(v3f pos, v3f dir)
167         {
168                 JMutexAutoLock lock(m_camera_mutex);
169                 m_camera_position = pos;
170                 m_camera_direction = dir;
171         }
172
173         /*void StartUpdater()
174         {
175                 updater.Start();
176         }
177
178         void StopUpdater()
179         {
180                 updater.setRun(false);
181                 while(updater.IsRunning())
182                         sleep_s(1);
183         }
184
185         bool UpdaterIsRunning()
186         {
187                 return updater.IsRunning();
188         }*/
189
190         static core::aabbox3d<f32> getNodeBox(v3s16 p)
191         {
192                 return core::aabbox3d<f32>(
193                         (float)p.X * BS - 0.5*BS,
194                         (float)p.Y * BS - 0.5*BS,
195                         (float)p.Z * BS - 0.5*BS,
196                         (float)p.X * BS + 0.5*BS,
197                         (float)p.Y * BS + 0.5*BS,
198                         (float)p.Z * BS + 0.5*BS
199                 );
200         }
201
202         //bool sectorExists(v2s16 p);
203         MapSector * getSectorNoGenerate(v2s16 p2d);
204         /*
205                 This is overloaded by ClientMap and ServerMap to allow
206                 their differing fetch methods.
207         */
208         virtual MapSector * emergeSector(v2s16 p) = 0;
209         
210         // Returns InvalidPositionException if not found
211         MapBlock * getBlockNoCreate(v3s16 p);
212         // Returns NULL if not found
213         MapBlock * getBlockNoCreateNoEx(v3s16 p);
214         
215         // Returns InvalidPositionException if not found
216         f32 getGroundHeight(v2s16 p, bool generate=false);
217         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
218
219         // Returns InvalidPositionException if not found
220         bool isNodeUnderground(v3s16 p);
221         
222         // virtual from NodeContainer
223         bool isValidPosition(v3s16 p)
224         {
225                 v3s16 blockpos = getNodeBlockPos(p);
226                 MapBlock *blockref;
227                 try{
228                         blockref = getBlockNoCreate(blockpos);
229                 }
230                 catch(InvalidPositionException &e)
231                 {
232                         return false;
233                 }
234                 return true;
235                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
236                 bool is_valid = blockref->isValidPosition(relpos);
237                 return is_valid;*/
238         }
239         
240         // virtual from NodeContainer
241         // throws InvalidPositionException if not found
242         MapNode getNode(v3s16 p)
243         {
244                 v3s16 blockpos = getNodeBlockPos(p);
245                 MapBlock * blockref = getBlockNoCreate(blockpos);
246                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
247
248                 return blockref->getNodeNoCheck(relpos);
249         }
250
251         // virtual from NodeContainer
252         // throws InvalidPositionException if not found
253         void setNode(v3s16 p, MapNode & n)
254         {
255                 v3s16 blockpos = getNodeBlockPos(p);
256                 MapBlock * blockref = getBlockNoCreate(blockpos);
257                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
258                 blockref->setNodeNoCheck(relpos, n);
259         }
260
261         /*MapNode getNodeGenerate(v3s16 p)
262         {
263                 v3s16 blockpos = getNodeBlockPos(p);
264                 MapBlock * blockref = getBlock(blockpos);
265                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
266
267                 return blockref->getNode(relpos);
268         }*/
269
270         /*void setNodeGenerate(v3s16 p, MapNode & n)
271         {
272                 v3s16 blockpos = getNodeBlockPos(p);
273                 MapBlock * blockref = getBlock(blockpos);
274                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
275                 blockref->setNode(relpos, n);
276         }*/
277
278         void unspreadLight(enum LightBank bank,
279                         core::map<v3s16, u8> & from_nodes,
280                         core::map<v3s16, bool> & light_sources,
281                         core::map<v3s16, MapBlock*> & modified_blocks);
282
283         void unLightNeighbors(enum LightBank bank,
284                         v3s16 pos, u8 lightwas,
285                         core::map<v3s16, bool> & light_sources,
286                         core::map<v3s16, MapBlock*> & modified_blocks);
287         
288         void spreadLight(enum LightBank bank,
289                         core::map<v3s16, bool> & from_nodes,
290                         core::map<v3s16, MapBlock*> & modified_blocks);
291         
292         void lightNeighbors(enum LightBank bank,
293                         v3s16 pos,
294                         core::map<v3s16, MapBlock*> & modified_blocks);
295
296         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
297
298         s16 propagateSunlight(v3s16 start,
299                         core::map<v3s16, MapBlock*> & modified_blocks);
300         
301         void updateLighting(enum LightBank bank,
302                         core::map<v3s16, MapBlock*>  & a_blocks,
303                         core::map<v3s16, MapBlock*> & modified_blocks);
304                         
305         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
306                         core::map<v3s16, MapBlock*> & modified_blocks);
307                         
308         /*
309                 These handle lighting but not faces.
310         */
311         void addNodeAndUpdate(v3s16 p, MapNode n,
312                         core::map<v3s16, MapBlock*> &modified_blocks);
313         void removeNodeAndUpdate(v3s16 p,
314                         core::map<v3s16, MapBlock*> &modified_blocks);
315         
316 #ifndef SERVER
317         void expireMeshes(bool only_daynight_diffed);
318         
319         /*
320                 Updates the faces of the given block and blocks on the
321                 leading edge.
322         */
323         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
324 #endif
325
326         /*
327                 Takes the blocks at the edges into account
328         */
329         bool dayNightDiffed(v3s16 blockpos);
330
331         //core::aabbox3d<s16> getDisplayedBlockArea();
332
333         //bool updateChangedVisibleArea();
334         
335         virtual void save(bool only_changed){assert(0);};
336
337         /*
338                 Updates usage timers
339         */
340         void timerUpdate(float dtime);
341         
342         // Takes cache into account
343         // sector mutex should be locked when calling
344         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
345         
346         // Returns count of deleted sectors
347         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
348                         core::list<v3s16> *deleted_blocks=NULL);
349
350         // For debug printing
351         virtual void PrintInfo(std::ostream &out);
352 };
353
354 // Master heightmap parameters
355 struct HMParams
356 {
357         HMParams()
358         {
359                 blocksize = 64;
360                 randmax = "constant 70.0";
361                 randfactor = "constant 0.6";
362                 base = "linear 0 80 0";
363         }
364         s16 blocksize;
365         std::string randmax;
366         std::string randfactor;
367         std::string base;
368 };
369
370 // Map parameters
371 struct MapParams
372 {
373         MapParams()
374         {
375                 plants_amount = 1.0;
376                 ravines_amount = 1.0;
377                 //max_objects_in_block = 30;
378         }
379         float plants_amount;
380         float ravines_amount;
381         //u16 max_objects_in_block;
382 };
383
384 /*
385         ServerMap
386
387         This is the only map class that is able to generate map.
388 */
389
390 class ServerMap : public Map
391 {
392 public:
393         /*
394                 savedir: directory to which map data should be saved
395         */
396         ServerMap(std::string savedir, HMParams hmp, MapParams mp);
397         ~ServerMap();
398
399         s32 mapType() const
400         {
401                 return MAPTYPE_SERVER;
402         }
403
404         /*
405                 Forcefully get a sector from somewhere
406         */
407         MapSector * emergeSector(v2s16 p);
408         /*
409                 Forcefully get a block from somewhere.
410
411                 Exceptions:
412                 - InvalidPositionException: possible if only_from_disk==true
413                 
414                 changed_blocks:
415                 - All already existing blocks that were modified are added.
416                         - If found on disk, nothing will be added.
417                         - If generated, the new block will not be included.
418
419                 lighting_invalidated_blocks:
420                 - All blocks that have heavy-to-calculate lighting changes
421                   are added.
422                         - updateLighting() should be called for these.
423                 
424                 - A block that is in changed_blocks may not be in
425                   lighting_invalidated_blocks.
426         */
427         MapBlock * emergeBlock(
428                         v3s16 p,
429                         bool only_from_disk,
430                         core::map<v3s16, MapBlock*> &changed_blocks,
431                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
432         );
433
434         void createDir(std::string path);
435         void createSaveDir();
436         // returns something like "xxxxxxxx"
437         std::string getSectorSubDir(v2s16 pos);
438         // returns something like "map/sectors/xxxxxxxx"
439         std::string getSectorDir(v2s16 pos);
440         std::string createSectorDir(v2s16 pos);
441         // dirname: final directory name
442         v2s16 getSectorPos(std::string dirname);
443         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
444
445         void save(bool only_changed);
446         void loadAll();
447
448         void saveMasterHeightmap();
449         void loadMasterHeightmap();
450
451         // The sector mutex should be locked when calling most of these
452         
453         // This only saves sector-specific data such as the heightmap
454         // (no MapBlocks)
455         void saveSectorMeta(ServerMapSector *sector);
456         MapSector* loadSectorMeta(std::string dirname);
457         
458         // Full load of a sector including all blocks.
459         // returns true on success, false on failure.
460         bool loadSectorFull(v2s16 p2d);
461         // If sector is not found in memory, try to load it from disk.
462         // Returns true if sector now resides in memory
463         //bool deFlushSector(v2s16 p2d);
464         
465         void saveBlock(MapBlock *block);
466         // This will generate a sector with getSector if not found.
467         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
468
469         // Gets from master heightmap
470         void getSectorCorners(v2s16 p2d, s16 *corners);
471
472         // For debug printing
473         virtual void PrintInfo(std::ostream &out);
474
475 private:
476         // Generator parameters
477         UnlimitedHeightmap *m_heightmap;
478         MapParams m_params;
479         PointAttributeDatabase m_padb;
480
481         std::string m_savedir;
482         bool m_map_saving_enabled;
483 };
484
485 #ifndef SERVER
486
487 struct MapDrawControl
488 {
489         MapDrawControl():
490                 range_all(false),
491                 wanted_range(50),
492                 wanted_max_blocks(0),
493                 wanted_min_range(0),
494                 blocks_drawn(0),
495                 blocks_would_have_drawn(0)
496         {
497         }
498         // Overrides limits by drawing everything
499         bool range_all;
500         // Wanted drawing range
501         float wanted_range;
502         // Maximum number of blocks to draw
503         u32 wanted_max_blocks;
504         // Blocks in this range are drawn regardless of number of blocks drawn
505         float wanted_min_range;
506         // Number of blocks rendered is written here by the renderer
507         u32 blocks_drawn;
508         // Number of blocks that would have been drawn in wanted_range
509         u32 blocks_would_have_drawn;
510 };
511
512 class Client;
513
514 /*
515         ClientMap
516         
517         This is the only map class that is able to render itself on screen.
518 */
519
520 class ClientMap : public Map, public scene::ISceneNode
521 {
522 public:
523         ClientMap(
524                         Client *client,
525                         MapDrawControl &control,
526                         scene::ISceneNode* parent,
527                         scene::ISceneManager* mgr,
528                         s32 id
529         );
530
531         ~ClientMap();
532
533         s32 mapType() const
534         {
535                 return MAPTYPE_CLIENT;
536         }
537
538         void drop()
539         {
540                 ISceneNode::drop();
541         }
542
543         /*
544                 Forcefully get a sector from somewhere
545         */
546         MapSector * emergeSector(v2s16 p);
547
548         void deSerializeSector(v2s16 p2d, std::istream &is);
549
550         /*
551                 ISceneNode methods
552         */
553
554         virtual void OnRegisterSceneNode();
555
556         virtual void render()
557         {
558                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
559                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
560                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
561         }
562         
563         virtual const core::aabbox3d<f32>& getBoundingBox() const
564         {
565                 return m_box;
566         }
567
568         void renderMap(video::IVideoDriver* driver, s32 pass);
569
570         /*
571                 Methods for setting temporary modifications to nodes for
572                 drawing.
573                 Return value is position of changed block.
574         */
575         v3s16 setTempMod(v3s16 p, NodeMod mod);
576         v3s16 clearTempMod(v3s16 p);
577         // Efficient implementation needs a cache of TempMods
578         //void clearTempMods();
579
580         // For debug printing
581         virtual void PrintInfo(std::ostream &out);
582         
583 private:
584         Client *m_client;
585         
586         core::aabbox3d<f32> m_box;
587         
588         // This is the master heightmap mesh
589         scene::SMesh *mesh;
590         JMutex mesh_mutex;
591         
592         MapDrawControl &m_control;
593 };
594
595 #endif
596
597 class MapVoxelManipulator : public VoxelManipulator
598 {
599 public:
600         MapVoxelManipulator(Map *map);
601         virtual ~MapVoxelManipulator();
602         
603         virtual void clear()
604         {
605                 VoxelManipulator::clear();
606                 m_loaded_blocks.clear();
607         }
608
609         virtual void emerge(VoxelArea a, s32 caller_id=-1);
610
611         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
612
613 private:
614         Map *m_map;
615         /*
616                 NOTE: This might be used or not
617                 bool is dummy value
618                 SUGG: How 'bout an another VoxelManipulator for storing the
619                       information about which block is loaded?
620         */
621         core::map<v3s16, bool> m_loaded_blocks;
622 };
623
624 #endif
625