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