ff3daf047930dece59f542b118011138a2689f51
[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 class ServerMap : public Map
385 {
386 public:
387         /*
388                 savedir: directory to which map data should be saved
389         */
390         ServerMap(std::string savedir, HMParams hmp, MapParams mp);
391         ~ServerMap();
392
393         s32 mapType() const
394         {
395                 return MAPTYPE_SERVER;
396         }
397
398         /*
399                 Forcefully get a sector from somewhere
400         */
401         MapSector * emergeSector(v2s16 p);
402         /*
403                 Forcefully get a block from somewhere.
404
405                 Exceptions:
406                 - InvalidPositionException: possible if only_from_disk==true
407                 
408                 changed_blocks:
409                 - All already existing blocks that were modified are added.
410                         - If found on disk, nothing will be added.
411                         - If generated, the new block will not be included.
412
413                 lighting_invalidated_blocks:
414                 - All blocks that have heavy-to-calculate lighting changes
415                   are added.
416                         - updateLighting() should be called for these.
417                 
418                 - A block that is in changed_blocks may not be in
419                   lighting_invalidated_blocks.
420         */
421         MapBlock * emergeBlock(
422                         v3s16 p,
423                         bool only_from_disk,
424                         core::map<v3s16, MapBlock*> &changed_blocks,
425                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
426         );
427
428         void createDir(std::string path);
429         void createSaveDir();
430         // returns something like "xxxxxxxx"
431         std::string getSectorSubDir(v2s16 pos);
432         // returns something like "map/sectors/xxxxxxxx"
433         std::string getSectorDir(v2s16 pos);
434         std::string createSectorDir(v2s16 pos);
435         // dirname: final directory name
436         v2s16 getSectorPos(std::string dirname);
437         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
438
439         void save(bool only_changed);
440         void loadAll();
441
442         void saveMasterHeightmap();
443         void loadMasterHeightmap();
444
445         // The sector mutex should be locked when calling most of these
446         
447         // This only saves sector-specific data such as the heightmap
448         // (no MapBlocks)
449         void saveSectorMeta(ServerMapSector *sector);
450         MapSector* loadSectorMeta(std::string dirname);
451         
452         // Full load of a sector including all blocks.
453         // returns true on success, false on failure.
454         bool loadSectorFull(v2s16 p2d);
455         // If sector is not found in memory, try to load it from disk.
456         // Returns true if sector now resides in memory
457         //bool deFlushSector(v2s16 p2d);
458         
459         void saveBlock(MapBlock *block);
460         // This will generate a sector with getSector if not found.
461         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
462
463         // Gets from master heightmap
464         void getSectorCorners(v2s16 p2d, s16 *corners);
465
466         // For debug printing
467         virtual void PrintInfo(std::ostream &out);
468
469 private:
470         UnlimitedHeightmap *m_heightmap;
471         MapParams m_params;
472
473         std::string m_savedir;
474         bool m_map_saving_enabled;
475 };
476
477 #ifndef SERVER
478
479 struct MapDrawControl
480 {
481         MapDrawControl():
482                 range_all(false),
483                 wanted_range(50),
484                 wanted_max_blocks(0),
485                 wanted_min_range(0),
486                 blocks_drawn(0),
487                 blocks_would_have_drawn(0)
488         {
489         }
490         // Overrides limits by drawing everything
491         bool range_all;
492         // Wanted drawing range
493         float wanted_range;
494         // Maximum number of blocks to draw
495         u32 wanted_max_blocks;
496         // Blocks in this range are drawn regardless of number of blocks drawn
497         float wanted_min_range;
498         // Number of blocks rendered is written here by the renderer
499         u32 blocks_drawn;
500         // Number of blocks that would have been drawn in wanted_range
501         u32 blocks_would_have_drawn;
502 };
503
504 class Client;
505
506 class ClientMap : public Map, public scene::ISceneNode
507 {
508 public:
509         ClientMap(
510                         Client *client,
511                         MapDrawControl &control,
512                         scene::ISceneNode* parent,
513                         scene::ISceneManager* mgr,
514                         s32 id
515         );
516
517         ~ClientMap();
518
519         s32 mapType() const
520         {
521                 return MAPTYPE_CLIENT;
522         }
523
524         void drop()
525         {
526                 ISceneNode::drop();
527         }
528
529         /*
530                 Forcefully get a sector from somewhere
531         */
532         MapSector * emergeSector(v2s16 p);
533
534         void deSerializeSector(v2s16 p2d, std::istream &is);
535
536         /*
537                 ISceneNode methods
538         */
539
540         virtual void OnRegisterSceneNode();
541
542         virtual void render()
543         {
544                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
545                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
546                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
547         }
548         
549         virtual const core::aabbox3d<f32>& getBoundingBox() const
550         {
551                 return m_box;
552         }
553
554         void renderMap(video::IVideoDriver* driver, s32 pass);
555
556         /*
557                 Methods for setting temporary modifications to nodes for
558                 drawing.
559                 Return value is position of changed block.
560         */
561         v3s16 setTempMod(v3s16 p, NodeMod mod);
562         v3s16 clearTempMod(v3s16 p);
563         // Efficient implementation needs a cache of TempMods
564         //void clearTempMods();
565
566         // For debug printing
567         virtual void PrintInfo(std::ostream &out);
568         
569 private:
570         Client *m_client;
571         
572         core::aabbox3d<f32> m_box;
573         
574         // This is the master heightmap mesh
575         scene::SMesh *mesh;
576         JMutex mesh_mutex;
577         
578         MapDrawControl &m_control;
579 };
580
581 #endif
582
583 class MapVoxelManipulator : public VoxelManipulator
584 {
585 public:
586         MapVoxelManipulator(Map *map);
587         virtual ~MapVoxelManipulator();
588         
589         virtual void clear()
590         {
591                 VoxelManipulator::clear();
592                 m_loaded_blocks.clear();
593         }
594
595         virtual void emerge(VoxelArea a, s32 caller_id=-1);
596
597         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
598
599 private:
600         Map *m_map;
601         /*
602                 NOTE: This might be used or not
603                 bool is dummy value
604                 SUGG: How 'bout an another VoxelManipulator for storing the
605                       information about which block is loaded?
606         */
607         core::map<v3s16, bool> m_loaded_blocks;
608 };
609
610 #endif
611