2 (c) 2010 Perttu Ahola <celeron55@gmail.com>
15 #define sleep_s(x) Sleep((x*1000))
18 #define sleep_s(x) sleep(x)
21 #include "common_irrlicht.h"
22 #include "heightmap.h"
23 #include "loadstatus.h"
26 #include "mapsector.h"
27 #include "constants.h"
32 A cache for short-term fast access to map data
34 NOTE: This doesn't really make anything more efficient
35 NOTE: Use VoxelManipulator, if possible
36 TODO: Get rid of this?
38 class MapBlockPointerCache : public NodeContainer
41 MapBlockPointerCache(Map *map);
42 ~MapBlockPointerCache();
44 virtual u16 nodeContainerId() const
46 return NODECONTAINER_ID_MAPBLOCKCACHE;
49 MapBlock * getBlockNoCreate(v3s16 p);
51 // virtual from NodeContainer
52 bool isValidPosition(v3s16 p)
54 v3s16 blockpos = getNodeBlockPos(p);
57 blockref = getBlockNoCreate(blockpos);
59 catch(InvalidPositionException &e)
66 // virtual from NodeContainer
67 MapNode getNode(v3s16 p)
69 v3s16 blockpos = getNodeBlockPos(p);
70 MapBlock * blockref = getBlockNoCreate(blockpos);
71 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
73 return blockref->getNodeNoCheck(relpos);
76 // virtual from NodeContainer
77 void setNode(v3s16 p, MapNode & n)
79 v3s16 blockpos = getNodeBlockPos(p);
80 MapBlock * block = getBlockNoCreate(blockpos);
81 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
82 block->setNodeNoCheck(relpos, n);
83 m_modified_blocks[blockpos] = block;
86 core::map<v3s16, MapBlock*> m_modified_blocks;
90 core::map<v3s16, MapBlock*> m_blocks;
92 u32 m_from_cache_count;
102 m_count_mutex.Init();
103 m_cache_mutex.Init();
104 m_waitcache_mutex.Init();
109 JMutexAutoLock waitcachelock(m_waitcache_mutex);
110 JMutexAutoLock countlock(m_count_mutex);
112 // If this is the first cache, grab the cache lock
114 m_cache_mutex.Lock();
121 JMutexAutoLock countlock(m_count_mutex);
127 // If this is the last one, release the cache lock
129 m_cache_mutex.Unlock();
133 This lock should be taken when removing stuff that can be
134 pointed by the cache.
136 You'll want to grab this in a SharedPtr.
138 JMutexAutoLock * waitCaches()
140 JMutexAutoLock waitcachelock(m_waitcache_mutex);
141 return new JMutexAutoLock(m_cache_mutex);
145 // Count of existing caches
147 JMutex m_count_mutex;
148 // This is locked always when there are some caches
149 JMutex m_cache_mutex;
150 // Locked so that when waitCaches() is called, no more caches are created
151 JMutex m_waitcache_mutex;
154 #define MAPTYPE_BASE 0
155 #define MAPTYPE_SERVER 1
156 #define MAPTYPE_CLIENT 2
158 class Map : public NodeContainer, public Heightmappish
162 std::ostream &m_dout;
164 core::map<v2s16, MapSector*> m_sectors;
165 JMutex m_sector_mutex;
167 v3f m_camera_position;
168 v3f m_camera_direction;
169 JMutex m_camera_mutex;
171 // Be sure to set this to NULL when the cached sector is deleted
172 MapSector *m_sector_cache;
173 v2s16 m_sector_cache_p;
175 WrapperHeightmap m_hwrapper;
179 v3s16 drawoffset; // for drawbox()
182 Used by MapBlockPointerCache.
184 waitCaches() can be called to remove all caches before continuing
186 CacheLock m_blockcachelock;
188 Map(std::ostream &dout);
191 virtual u16 nodeContainerId() const
193 return NODECONTAINER_ID_MAP;
196 virtual s32 mapType() const
201 void updateCamera(v3f pos, v3f dir)
203 JMutexAutoLock lock(m_camera_mutex);
204 m_camera_position = pos;
205 m_camera_direction = dir;
208 /*void StartUpdater()
215 updater.setRun(false);
216 while(updater.IsRunning())
220 bool UpdaterIsRunning()
222 return updater.IsRunning();
225 static core::aabbox3d<f32> getNodeBox(v3s16 p)
227 return core::aabbox3d<f32>(
228 (float)p.X * BS - 0.5*BS,
229 (float)p.Y * BS - 0.5*BS,
230 (float)p.Z * BS - 0.5*BS,
231 (float)p.X * BS + 0.5*BS,
232 (float)p.Y * BS + 0.5*BS,
233 (float)p.Z * BS + 0.5*BS
237 //bool sectorExists(v2s16 p);
238 MapSector * getSectorNoGenerate(v2s16 p2d);
240 This is overloaded by ClientMap and ServerMap to allow
241 their differing fetch methods.
243 virtual MapSector * emergeSector(v2s16 p) = 0;
245 // Returns InvalidPositionException if not found
246 MapBlock * getBlockNoCreate(v3s16 p);
247 //virtual MapBlock * getBlock(v3s16 p, bool generate=true);
249 // Returns InvalidPositionException if not found
250 f32 getGroundHeight(v2s16 p, bool generate=false);
251 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
253 // Returns InvalidPositionException if not found
254 bool isNodeUnderground(v3s16 p);
256 // virtual from NodeContainer
257 bool isValidPosition(v3s16 p)
259 v3s16 blockpos = getNodeBlockPos(p);
262 blockref = getBlockNoCreate(blockpos);
264 catch(InvalidPositionException &e)
269 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
270 bool is_valid = blockref->isValidPosition(relpos);
274 // virtual from NodeContainer
275 MapNode getNode(v3s16 p)
277 v3s16 blockpos = getNodeBlockPos(p);
278 MapBlock * blockref = getBlockNoCreate(blockpos);
279 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
281 return blockref->getNodeNoCheck(relpos);
284 // virtual from NodeContainer
285 void setNode(v3s16 p, MapNode & n)
287 v3s16 blockpos = getNodeBlockPos(p);
288 MapBlock * blockref = getBlockNoCreate(blockpos);
289 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
290 blockref->setNodeNoCheck(relpos, n);
293 /*MapNode getNodeGenerate(v3s16 p)
295 v3s16 blockpos = getNodeBlockPos(p);
296 MapBlock * blockref = getBlock(blockpos);
297 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
299 return blockref->getNode(relpos);
302 /*void setNodeGenerate(v3s16 p, MapNode & n)
304 v3s16 blockpos = getNodeBlockPos(p);
305 MapBlock * blockref = getBlock(blockpos);
306 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
307 blockref->setNode(relpos, n);
310 void unspreadLight(core::map<v3s16, u8> & from_nodes,
311 core::map<v3s16, bool> & light_sources,
312 core::map<v3s16, MapBlock*> & modified_blocks);
314 void unLightNeighbors(v3s16 pos, u8 lightwas,
315 core::map<v3s16, bool> & light_sources,
316 core::map<v3s16, MapBlock*> & modified_blocks);
318 void spreadLight(core::map<v3s16, bool> & from_nodes,
319 core::map<v3s16, MapBlock*> & modified_blocks);
321 void lightNeighbors(v3s16 pos,
322 core::map<v3s16, MapBlock*> & modified_blocks);
324 v3s16 getBrightestNeighbour(v3s16 p);
326 s16 propagateSunlight(v3s16 start,
327 core::map<v3s16, MapBlock*> & modified_blocks);
329 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
330 core::map<v3s16, MapBlock*> & modified_blocks);
333 These handle lighting but not faces.
335 void addNodeAndUpdate(v3s16 p, MapNode n,
336 core::map<v3s16, MapBlock*> &modified_blocks);
337 void removeNodeAndUpdate(v3s16 p,
338 core::map<v3s16, MapBlock*> &modified_blocks);
341 Updates the faces of the given block and blocks on the
344 void updateMeshes(v3s16 blockpos);
346 //core::aabbox3d<s16> getDisplayedBlockArea();
348 //bool updateChangedVisibleArea();
350 virtual void save(bool only_changed){assert(0);};
355 void timerUpdate(float dtime);
357 // Takes cache into account
358 // sector mutex should be locked when calling
359 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
361 // Returns count of deleted sectors
362 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
363 core::list<v3s16> *deleted_blocks=NULL);
365 // For debug printing
366 virtual void PrintInfo(std::ostream &out);
369 // Master heightmap parameters
375 randmax = "constant 70.0";
376 randfactor = "constant 0.6";
377 base = "linear 0 80 0";
381 std::string randfactor;
391 ravines_amount = 1.0;
392 //max_objects_in_block = 30;
395 float ravines_amount;
396 //u16 max_objects_in_block;
399 class ServerMap : public Map
403 savedir: directory to which map data should be saved
405 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
410 return MAPTYPE_SERVER;
414 Forcefully get a sector from somewhere
416 MapSector * emergeSector(v2s16 p);
418 Forcefully get a block from somewhere.
421 - InvalidPositionException: possible if only_from_disk==true
424 - All already existing blocks that were modified are added.
425 - If found on disk, nothing will be added.
426 - If generated, the new block will not be included.
428 lighting_invalidated_blocks:
429 - All blocks that have heavy-to-calculate lighting changes
431 - updateLighting() should be called for these.
433 - A block that is in changed_blocks may not be in
434 lighting_invalidated_blocks.
436 MapBlock * emergeBlock(
439 core::map<v3s16, MapBlock*> &changed_blocks,
440 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
443 void createDir(std::string path);
444 void createSaveDir();
445 // returns something like "xxxxxxxx"
446 std::string getSectorSubDir(v2s16 pos);
447 // returns something like "map/sectors/xxxxxxxx"
448 std::string getSectorDir(v2s16 pos);
449 std::string createSectorDir(v2s16 pos);
450 // dirname: final directory name
451 v2s16 getSectorPos(std::string dirname);
452 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
454 void save(bool only_changed);
457 void saveMasterHeightmap();
458 void loadMasterHeightmap();
460 // The sector mutex should be locked when calling most of these
462 // This only saves sector-specific data such as the heightmap
464 void saveSectorMeta(ServerMapSector *sector);
465 MapSector* loadSectorMeta(std::string dirname);
467 // Full load of a sector including all blocks.
468 // returns true on success, false on failure.
469 bool loadSectorFull(v2s16 p2d);
470 // If sector is not found in memory, try to load it from disk.
471 // Returns true if sector now resides in memory
472 //bool deFlushSector(v2s16 p2d);
474 void saveBlock(MapBlock *block);
475 // This will generate a sector with getSector if not found.
476 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
478 // Gets from master heightmap
479 void getSectorCorners(v2s16 p2d, s16 *corners);
481 // For debug printing
482 virtual void PrintInfo(std::ostream &out);
485 UnlimitedHeightmap *m_heightmap;
488 std::string m_savedir;
489 bool m_map_saving_enabled;
494 class ClientMap : public Map, public scene::ISceneNode
499 video::SMaterial *materials,
500 scene::ISceneNode* parent,
501 scene::ISceneManager* mgr,
509 return MAPTYPE_CLIENT;
513 Forcefully get a sector from somewhere
515 MapSector * emergeSector(v2s16 p);
517 void deSerializeSector(v2s16 p2d, std::istream &is);
523 virtual void OnRegisterSceneNode()
527 //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
528 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
529 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
532 ISceneNode::OnRegisterSceneNode();
535 virtual void render()
537 video::IVideoDriver* driver = SceneManager->getVideoDriver();
538 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
539 renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass());
542 virtual const core::aabbox3d<f32>& getBoundingBox() const
547 void renderMap(video::IVideoDriver* driver,
548 video::SMaterial *materials, s32 pass);
550 // Update master heightmap mesh
553 // For debug printing
554 virtual void PrintInfo(std::ostream &out);
559 video::SMaterial *m_materials;
561 core::aabbox3d<f32> m_box;
563 // This is the master heightmap mesh