3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
30 #define sleep_s(x) Sleep((x*1000))
33 #define sleep_s(x) sleep(x)
36 #include "common_irrlicht.h"
37 #include "heightmap.h"
40 #include "mapsector.h"
41 #include "constants.h"
47 A cache for short-term fast access to map data
49 NOTE: This doesn't really make anything more efficient
50 NOTE: Use VoxelManipulator, if possible
51 TODO: Get rid of this?
52 NOTE: CONFIRMED: THIS CACHE DOESN'T MAKE ANYTHING ANY FASTER
54 class MapBlockPointerCache : public NodeContainer
57 MapBlockPointerCache(Map *map);
58 ~MapBlockPointerCache();
60 virtual u16 nodeContainerId() const
62 return NODECONTAINER_ID_MAPBLOCKCACHE;
65 MapBlock * getBlockNoCreate(v3s16 p);
67 // virtual from NodeContainer
68 bool isValidPosition(v3s16 p)
70 v3s16 blockpos = getNodeBlockPos(p);
73 blockref = getBlockNoCreate(blockpos);
75 catch(InvalidPositionException &e)
82 // virtual from NodeContainer
83 MapNode getNode(v3s16 p)
85 v3s16 blockpos = getNodeBlockPos(p);
86 MapBlock * blockref = getBlockNoCreate(blockpos);
87 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
89 return blockref->getNodeNoCheck(relpos);
92 // virtual from NodeContainer
93 void setNode(v3s16 p, MapNode & n)
95 v3s16 blockpos = getNodeBlockPos(p);
96 MapBlock * block = getBlockNoCreate(blockpos);
97 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
98 block->setNodeNoCheck(relpos, n);
99 m_modified_blocks[blockpos] = block;
102 core::map<v3s16, MapBlock*> m_modified_blocks;
106 core::map<v3s16, MapBlock*> m_blocks;
108 u32 m_from_cache_count;
109 u32 m_from_map_count;
118 m_count_mutex.Init();
119 m_cache_mutex.Init();
120 m_waitcache_mutex.Init();
125 //dstream<<"cacheCreated() begin"<<std::endl;
126 JMutexAutoLock waitcachelock(m_waitcache_mutex);
127 JMutexAutoLock countlock(m_count_mutex);
129 // If this is the first cache, grab the cache lock
131 m_cache_mutex.Lock();
135 //dstream<<"cacheCreated() end"<<std::endl;
140 //dstream<<"cacheRemoved() begin"<<std::endl;
141 JMutexAutoLock countlock(m_count_mutex);
147 // If this is the last one, release the cache lock
149 m_cache_mutex.Unlock();
151 //dstream<<"cacheRemoved() end"<<std::endl;
155 This lock should be taken when removing stuff that can be
156 pointed by the cache.
158 You'll want to grab this in a SharedPtr.
160 JMutexAutoLock * waitCaches()
162 //dstream<<"waitCaches() begin"<<std::endl;
163 JMutexAutoLock waitcachelock(m_waitcache_mutex);
164 JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
165 //dstream<<"waitCaches() end"<<std::endl;
170 // Count of existing caches
172 JMutex m_count_mutex;
173 // This is locked always when there are some caches
174 JMutex m_cache_mutex;
175 // Locked so that when waitCaches() is called, no more caches are created
176 JMutex m_waitcache_mutex;
179 #define MAPTYPE_BASE 0
180 #define MAPTYPE_SERVER 1
181 #define MAPTYPE_CLIENT 2
183 class Map : public NodeContainer, public Heightmappish
187 std::ostream &m_dout;
189 core::map<v2s16, MapSector*> m_sectors;
190 JMutex m_sector_mutex;
192 v3f m_camera_position;
193 v3f m_camera_direction;
194 JMutex m_camera_mutex;
196 // Be sure to set this to NULL when the cached sector is deleted
197 MapSector *m_sector_cache;
198 v2s16 m_sector_cache_p;
200 WrapperHeightmap m_hwrapper;
204 v3s16 drawoffset; // for drawbox()
207 Used by MapBlockPointerCache.
209 waitCaches() can be called to remove all caches before continuing
211 CacheLock m_blockcachelock;
213 Map(std::ostream &dout);
216 virtual u16 nodeContainerId() const
218 return NODECONTAINER_ID_MAP;
221 virtual s32 mapType() const
231 void updateCamera(v3f pos, v3f dir)
233 JMutexAutoLock lock(m_camera_mutex);
234 m_camera_position = pos;
235 m_camera_direction = dir;
238 /*void StartUpdater()
245 updater.setRun(false);
246 while(updater.IsRunning())
250 bool UpdaterIsRunning()
252 return updater.IsRunning();
255 static core::aabbox3d<f32> getNodeBox(v3s16 p)
257 return core::aabbox3d<f32>(
258 (float)p.X * BS - 0.5*BS,
259 (float)p.Y * BS - 0.5*BS,
260 (float)p.Z * BS - 0.5*BS,
261 (float)p.X * BS + 0.5*BS,
262 (float)p.Y * BS + 0.5*BS,
263 (float)p.Z * BS + 0.5*BS
267 //bool sectorExists(v2s16 p);
268 MapSector * getSectorNoGenerate(v2s16 p2d);
270 This is overloaded by ClientMap and ServerMap to allow
271 their differing fetch methods.
273 virtual MapSector * emergeSector(v2s16 p) = 0;
275 // Returns InvalidPositionException if not found
276 MapBlock * getBlockNoCreate(v3s16 p);
277 // Returns NULL if not found
278 MapBlock * getBlockNoCreateNoEx(v3s16 p);
280 // Returns InvalidPositionException if not found
281 f32 getGroundHeight(v2s16 p, bool generate=false);
282 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
284 // Returns InvalidPositionException if not found
285 bool isNodeUnderground(v3s16 p);
287 // virtual from NodeContainer
288 bool isValidPosition(v3s16 p)
290 v3s16 blockpos = getNodeBlockPos(p);
293 blockref = getBlockNoCreate(blockpos);
295 catch(InvalidPositionException &e)
300 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
301 bool is_valid = blockref->isValidPosition(relpos);
305 // virtual from NodeContainer
306 MapNode getNode(v3s16 p)
308 v3s16 blockpos = getNodeBlockPos(p);
309 MapBlock * blockref = getBlockNoCreate(blockpos);
310 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
312 return blockref->getNodeNoCheck(relpos);
315 // virtual from NodeContainer
316 void setNode(v3s16 p, MapNode & n)
318 v3s16 blockpos = getNodeBlockPos(p);
319 MapBlock * blockref = getBlockNoCreate(blockpos);
320 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
321 blockref->setNodeNoCheck(relpos, n);
324 /*MapNode getNodeGenerate(v3s16 p)
326 v3s16 blockpos = getNodeBlockPos(p);
327 MapBlock * blockref = getBlock(blockpos);
328 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
330 return blockref->getNode(relpos);
333 /*void setNodeGenerate(v3s16 p, MapNode & n)
335 v3s16 blockpos = getNodeBlockPos(p);
336 MapBlock * blockref = getBlock(blockpos);
337 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
338 blockref->setNode(relpos, n);
341 void unspreadLight(enum LightBank bank,
342 core::map<v3s16, u8> & from_nodes,
343 core::map<v3s16, bool> & light_sources,
344 core::map<v3s16, MapBlock*> & modified_blocks);
346 void unLightNeighbors(enum LightBank bank,
347 v3s16 pos, u8 lightwas,
348 core::map<v3s16, bool> & light_sources,
349 core::map<v3s16, MapBlock*> & modified_blocks);
351 void spreadLight(enum LightBank bank,
352 core::map<v3s16, bool> & from_nodes,
353 core::map<v3s16, MapBlock*> & modified_blocks);
355 void lightNeighbors(enum LightBank bank,
357 core::map<v3s16, MapBlock*> & modified_blocks);
359 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
361 s16 propagateSunlight(v3s16 start,
362 core::map<v3s16, MapBlock*> & modified_blocks);
364 void updateLighting(enum LightBank bank,
365 core::map<v3s16, MapBlock*> & a_blocks,
366 core::map<v3s16, MapBlock*> & modified_blocks);
368 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
369 core::map<v3s16, MapBlock*> & modified_blocks);
372 These handle lighting but not faces.
374 void addNodeAndUpdate(v3s16 p, MapNode n,
375 core::map<v3s16, MapBlock*> &modified_blocks);
376 void removeNodeAndUpdate(v3s16 p,
377 core::map<v3s16, MapBlock*> &modified_blocks);
380 void expireMeshes(bool only_daynight_diffed);
383 Updates the faces of the given block and blocks on the
386 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
390 Takes the blocks at the edges into account
392 bool dayNightDiffed(v3s16 blockpos);
394 //core::aabbox3d<s16> getDisplayedBlockArea();
396 //bool updateChangedVisibleArea();
398 virtual void save(bool only_changed){assert(0);};
403 void timerUpdate(float dtime);
405 // Takes cache into account
406 // sector mutex should be locked when calling
407 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
409 // Returns count of deleted sectors
410 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
411 core::list<v3s16> *deleted_blocks=NULL);
413 // For debug printing
414 virtual void PrintInfo(std::ostream &out);
417 // Master heightmap parameters
423 randmax = "constant 70.0";
424 randfactor = "constant 0.6";
425 base = "linear 0 80 0";
429 std::string randfactor;
439 ravines_amount = 1.0;
440 //max_objects_in_block = 30;
443 float ravines_amount;
444 //u16 max_objects_in_block;
447 class ServerMap : public Map
451 savedir: directory to which map data should be saved
453 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
458 return MAPTYPE_SERVER;
462 Forcefully get a sector from somewhere
464 MapSector * emergeSector(v2s16 p);
466 Forcefully get a block from somewhere.
469 - InvalidPositionException: possible if only_from_disk==true
472 - All already existing blocks that were modified are added.
473 - If found on disk, nothing will be added.
474 - If generated, the new block will not be included.
476 lighting_invalidated_blocks:
477 - All blocks that have heavy-to-calculate lighting changes
479 - updateLighting() should be called for these.
481 - A block that is in changed_blocks may not be in
482 lighting_invalidated_blocks.
484 MapBlock * emergeBlock(
487 core::map<v3s16, MapBlock*> &changed_blocks,
488 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
491 void createDir(std::string path);
492 void createSaveDir();
493 // returns something like "xxxxxxxx"
494 std::string getSectorSubDir(v2s16 pos);
495 // returns something like "map/sectors/xxxxxxxx"
496 std::string getSectorDir(v2s16 pos);
497 std::string createSectorDir(v2s16 pos);
498 // dirname: final directory name
499 v2s16 getSectorPos(std::string dirname);
500 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
502 void save(bool only_changed);
505 void saveMasterHeightmap();
506 void loadMasterHeightmap();
508 // The sector mutex should be locked when calling most of these
510 // This only saves sector-specific data such as the heightmap
512 void saveSectorMeta(ServerMapSector *sector);
513 MapSector* loadSectorMeta(std::string dirname);
515 // Full load of a sector including all blocks.
516 // returns true on success, false on failure.
517 bool loadSectorFull(v2s16 p2d);
518 // If sector is not found in memory, try to load it from disk.
519 // Returns true if sector now resides in memory
520 //bool deFlushSector(v2s16 p2d);
522 void saveBlock(MapBlock *block);
523 // This will generate a sector with getSector if not found.
524 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
526 // Gets from master heightmap
527 void getSectorCorners(v2s16 p2d, s16 *corners);
529 // For debug printing
530 virtual void PrintInfo(std::ostream &out);
533 UnlimitedHeightmap *m_heightmap;
536 std::string m_savedir;
537 bool m_map_saving_enabled;
544 class ClientMap : public Map, public scene::ISceneNode
550 s16 &viewing_range_nodes,
551 bool &viewing_range_all,
552 scene::ISceneNode* parent,
553 scene::ISceneManager* mgr,
561 return MAPTYPE_CLIENT;
570 Forcefully get a sector from somewhere
572 MapSector * emergeSector(v2s16 p);
574 void deSerializeSector(v2s16 p2d, std::istream &is);
580 virtual void OnRegisterSceneNode();
582 virtual void render()
584 video::IVideoDriver* driver = SceneManager->getVideoDriver();
585 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
586 renderMap(driver, SceneManager->getSceneNodeRenderPass());
589 virtual const core::aabbox3d<f32>& getBoundingBox() const
594 void renderMap(video::IVideoDriver* driver, s32 pass);
597 Methods for setting temporary modifications to nodes for
599 Return value is position of changed block.
601 v3s16 setTempMod(v3s16 p, NodeMod mod);
602 v3s16 clearTempMod(v3s16 p);
603 // Efficient implementation needs a cache of TempMods
604 //void clearTempMods();
606 // For debug printing
607 virtual void PrintInfo(std::ostream &out);
612 core::aabbox3d<f32> m_box;
614 // This is the master heightmap mesh
618 JMutex &m_range_mutex;
619 s16 &m_viewing_range_nodes;
620 bool &m_viewing_range_all;
625 class MapVoxelManipulator : public VoxelManipulator
628 MapVoxelManipulator(Map *map);
629 virtual ~MapVoxelManipulator();
633 VoxelManipulator::clear();
634 m_loaded_blocks.clear();
637 virtual void emerge(VoxelArea a, s32 caller_id=-1);
639 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
644 NOTE: This might be used or not
646 SUGG: How 'bout an another VoxelManipulator for storing the
647 information about which block is loaded?
649 core::map<v3s16, bool> m_loaded_blocks;