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 dstream<<"cacheCreated() begin"<<std::endl;
110 JMutexAutoLock waitcachelock(m_waitcache_mutex);
111 JMutexAutoLock countlock(m_count_mutex);
113 // If this is the first cache, grab the cache lock
115 m_cache_mutex.Lock();
119 dstream<<"cacheCreated() end"<<std::endl;
124 dstream<<"cacheRemoved() begin"<<std::endl;
125 JMutexAutoLock countlock(m_count_mutex);
131 // If this is the last one, release the cache lock
133 m_cache_mutex.Unlock();
135 dstream<<"cacheRemoved() end"<<std::endl;
139 This lock should be taken when removing stuff that can be
140 pointed by the cache.
142 You'll want to grab this in a SharedPtr.
144 JMutexAutoLock * waitCaches()
146 dstream<<"waitCaches() begin"<<std::endl;
147 JMutexAutoLock waitcachelock(m_waitcache_mutex);
148 JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
149 dstream<<"waitCaches() end"<<std::endl;
154 // Count of existing caches
156 JMutex m_count_mutex;
157 // This is locked always when there are some caches
158 JMutex m_cache_mutex;
159 // Locked so that when waitCaches() is called, no more caches are created
160 JMutex m_waitcache_mutex;
163 #define MAPTYPE_BASE 0
164 #define MAPTYPE_SERVER 1
165 #define MAPTYPE_CLIENT 2
167 class Map : public NodeContainer, public Heightmappish
171 std::ostream &m_dout;
173 core::map<v2s16, MapSector*> m_sectors;
174 JMutex m_sector_mutex;
176 v3f m_camera_position;
177 v3f m_camera_direction;
178 JMutex m_camera_mutex;
180 // Be sure to set this to NULL when the cached sector is deleted
181 MapSector *m_sector_cache;
182 v2s16 m_sector_cache_p;
184 WrapperHeightmap m_hwrapper;
188 v3s16 drawoffset; // for drawbox()
191 Used by MapBlockPointerCache.
193 waitCaches() can be called to remove all caches before continuing
195 CacheLock m_blockcachelock;
197 Map(std::ostream &dout);
200 virtual u16 nodeContainerId() const
202 return NODECONTAINER_ID_MAP;
205 virtual s32 mapType() const
210 void updateCamera(v3f pos, v3f dir)
212 JMutexAutoLock lock(m_camera_mutex);
213 m_camera_position = pos;
214 m_camera_direction = dir;
217 /*void StartUpdater()
224 updater.setRun(false);
225 while(updater.IsRunning())
229 bool UpdaterIsRunning()
231 return updater.IsRunning();
234 static core::aabbox3d<f32> getNodeBox(v3s16 p)
236 return core::aabbox3d<f32>(
237 (float)p.X * BS - 0.5*BS,
238 (float)p.Y * BS - 0.5*BS,
239 (float)p.Z * BS - 0.5*BS,
240 (float)p.X * BS + 0.5*BS,
241 (float)p.Y * BS + 0.5*BS,
242 (float)p.Z * BS + 0.5*BS
246 //bool sectorExists(v2s16 p);
247 MapSector * getSectorNoGenerate(v2s16 p2d);
249 This is overloaded by ClientMap and ServerMap to allow
250 their differing fetch methods.
252 virtual MapSector * emergeSector(v2s16 p) = 0;
254 // Returns InvalidPositionException if not found
255 MapBlock * getBlockNoCreate(v3s16 p);
256 //virtual MapBlock * getBlock(v3s16 p, bool generate=true);
258 // Returns InvalidPositionException if not found
259 f32 getGroundHeight(v2s16 p, bool generate=false);
260 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
262 // Returns InvalidPositionException if not found
263 bool isNodeUnderground(v3s16 p);
265 // virtual from NodeContainer
266 bool isValidPosition(v3s16 p)
268 v3s16 blockpos = getNodeBlockPos(p);
271 blockref = getBlockNoCreate(blockpos);
273 catch(InvalidPositionException &e)
278 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
279 bool is_valid = blockref->isValidPosition(relpos);
283 // virtual from NodeContainer
284 MapNode getNode(v3s16 p)
286 v3s16 blockpos = getNodeBlockPos(p);
287 MapBlock * blockref = getBlockNoCreate(blockpos);
288 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
290 return blockref->getNodeNoCheck(relpos);
293 // virtual from NodeContainer
294 void setNode(v3s16 p, MapNode & n)
296 v3s16 blockpos = getNodeBlockPos(p);
297 MapBlock * blockref = getBlockNoCreate(blockpos);
298 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
299 blockref->setNodeNoCheck(relpos, n);
302 /*MapNode getNodeGenerate(v3s16 p)
304 v3s16 blockpos = getNodeBlockPos(p);
305 MapBlock * blockref = getBlock(blockpos);
306 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
308 return blockref->getNode(relpos);
311 /*void setNodeGenerate(v3s16 p, MapNode & n)
313 v3s16 blockpos = getNodeBlockPos(p);
314 MapBlock * blockref = getBlock(blockpos);
315 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
316 blockref->setNode(relpos, n);
319 void unspreadLight(core::map<v3s16, u8> & from_nodes,
320 core::map<v3s16, bool> & light_sources,
321 core::map<v3s16, MapBlock*> & modified_blocks);
323 void unLightNeighbors(v3s16 pos, u8 lightwas,
324 core::map<v3s16, bool> & light_sources,
325 core::map<v3s16, MapBlock*> & modified_blocks);
327 void spreadLight(core::map<v3s16, bool> & from_nodes,
328 core::map<v3s16, MapBlock*> & modified_blocks);
330 void lightNeighbors(v3s16 pos,
331 core::map<v3s16, MapBlock*> & modified_blocks);
333 v3s16 getBrightestNeighbour(v3s16 p);
335 s16 propagateSunlight(v3s16 start,
336 core::map<v3s16, MapBlock*> & modified_blocks);
338 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
339 core::map<v3s16, MapBlock*> & modified_blocks);
342 These handle lighting but not faces.
344 void addNodeAndUpdate(v3s16 p, MapNode n,
345 core::map<v3s16, MapBlock*> &modified_blocks);
346 void removeNodeAndUpdate(v3s16 p,
347 core::map<v3s16, MapBlock*> &modified_blocks);
350 Updates the faces of the given block and blocks on the
353 void updateMeshes(v3s16 blockpos);
355 //core::aabbox3d<s16> getDisplayedBlockArea();
357 //bool updateChangedVisibleArea();
359 virtual void save(bool only_changed){assert(0);};
364 void timerUpdate(float dtime);
366 // Takes cache into account
367 // sector mutex should be locked when calling
368 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
370 // Returns count of deleted sectors
371 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
372 core::list<v3s16> *deleted_blocks=NULL);
374 // For debug printing
375 virtual void PrintInfo(std::ostream &out);
378 // Master heightmap parameters
384 randmax = "constant 70.0";
385 randfactor = "constant 0.6";
386 base = "linear 0 80 0";
390 std::string randfactor;
400 ravines_amount = 1.0;
401 //max_objects_in_block = 30;
404 float ravines_amount;
405 //u16 max_objects_in_block;
408 class ServerMap : public Map
412 savedir: directory to which map data should be saved
414 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
419 return MAPTYPE_SERVER;
423 Forcefully get a sector from somewhere
425 MapSector * emergeSector(v2s16 p);
427 Forcefully get a block from somewhere.
430 - InvalidPositionException: possible if only_from_disk==true
433 - All already existing blocks that were modified are added.
434 - If found on disk, nothing will be added.
435 - If generated, the new block will not be included.
437 lighting_invalidated_blocks:
438 - All blocks that have heavy-to-calculate lighting changes
440 - updateLighting() should be called for these.
442 - A block that is in changed_blocks may not be in
443 lighting_invalidated_blocks.
445 MapBlock * emergeBlock(
448 core::map<v3s16, MapBlock*> &changed_blocks,
449 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
452 void createDir(std::string path);
453 void createSaveDir();
454 // returns something like "xxxxxxxx"
455 std::string getSectorSubDir(v2s16 pos);
456 // returns something like "map/sectors/xxxxxxxx"
457 std::string getSectorDir(v2s16 pos);
458 std::string createSectorDir(v2s16 pos);
459 // dirname: final directory name
460 v2s16 getSectorPos(std::string dirname);
461 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
463 void save(bool only_changed);
466 void saveMasterHeightmap();
467 void loadMasterHeightmap();
469 // The sector mutex should be locked when calling most of these
471 // This only saves sector-specific data such as the heightmap
473 void saveSectorMeta(ServerMapSector *sector);
474 MapSector* loadSectorMeta(std::string dirname);
476 // Full load of a sector including all blocks.
477 // returns true on success, false on failure.
478 bool loadSectorFull(v2s16 p2d);
479 // If sector is not found in memory, try to load it from disk.
480 // Returns true if sector now resides in memory
481 //bool deFlushSector(v2s16 p2d);
483 void saveBlock(MapBlock *block);
484 // This will generate a sector with getSector if not found.
485 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
487 // Gets from master heightmap
488 void getSectorCorners(v2s16 p2d, s16 *corners);
490 // For debug printing
491 virtual void PrintInfo(std::ostream &out);
494 UnlimitedHeightmap *m_heightmap;
497 std::string m_savedir;
498 bool m_map_saving_enabled;
503 class ClientMap : public Map, public scene::ISceneNode
508 video::SMaterial *materials,
509 scene::ISceneNode* parent,
510 scene::ISceneManager* mgr,
518 return MAPTYPE_CLIENT;
522 Forcefully get a sector from somewhere
524 MapSector * emergeSector(v2s16 p);
526 void deSerializeSector(v2s16 p2d, std::istream &is);
532 virtual void OnRegisterSceneNode()
536 //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
537 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
538 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
541 ISceneNode::OnRegisterSceneNode();
544 virtual void render()
546 video::IVideoDriver* driver = SceneManager->getVideoDriver();
547 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
548 renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass());
551 virtual const core::aabbox3d<f32>& getBoundingBox() const
556 void renderMap(video::IVideoDriver* driver,
557 video::SMaterial *materials, s32 pass);
559 // Update master heightmap mesh
562 // For debug printing
563 virtual void PrintInfo(std::ostream &out);
568 video::SMaterial *m_materials;
570 core::aabbox3d<f32> m_box;
572 // This is the master heightmap mesh