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"
48 A cache for short-term fast access to map data
50 NOTE: This doesn't really make anything more efficient
51 NOTE: Use VoxelManipulator, if possible
52 TODO: Get rid of this?
53 NOTE: CONFIRMED: THIS CACHE DOESN'T MAKE ANYTHING ANY FASTER
55 class MapBlockPointerCache : public NodeContainer
58 MapBlockPointerCache(Map *map);
59 ~MapBlockPointerCache();
61 virtual u16 nodeContainerId() const
63 return NODECONTAINER_ID_MAPBLOCKCACHE;
66 MapBlock * getBlockNoCreate(v3s16 p);
68 // virtual from NodeContainer
69 bool isValidPosition(v3s16 p)
71 v3s16 blockpos = getNodeBlockPos(p);
74 blockref = getBlockNoCreate(blockpos);
76 catch(InvalidPositionException &e)
83 // virtual from NodeContainer
84 MapNode getNode(v3s16 p)
86 v3s16 blockpos = getNodeBlockPos(p);
87 MapBlock * blockref = getBlockNoCreate(blockpos);
88 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
90 return blockref->getNodeNoCheck(relpos);
93 // virtual from NodeContainer
94 void setNode(v3s16 p, MapNode & n)
96 v3s16 blockpos = getNodeBlockPos(p);
97 MapBlock * block = getBlockNoCreate(blockpos);
98 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
99 block->setNodeNoCheck(relpos, n);
100 m_modified_blocks[blockpos] = block;
103 core::map<v3s16, MapBlock*> m_modified_blocks;
107 core::map<v3s16, MapBlock*> m_blocks;
109 u32 m_from_cache_count;
110 u32 m_from_map_count;
120 m_count_mutex.Init();
121 m_cache_mutex.Init();
122 m_waitcache_mutex.Init();
127 //dstream<<"cacheCreated() begin"<<std::endl;
128 JMutexAutoLock waitcachelock(m_waitcache_mutex);
129 JMutexAutoLock countlock(m_count_mutex);
131 // If this is the first cache, grab the cache lock
133 m_cache_mutex.Lock();
137 //dstream<<"cacheCreated() end"<<std::endl;
142 //dstream<<"cacheRemoved() begin"<<std::endl;
143 JMutexAutoLock countlock(m_count_mutex);
149 // If this is the last one, release the cache lock
151 m_cache_mutex.Unlock();
153 //dstream<<"cacheRemoved() end"<<std::endl;
157 This lock should be taken when removing stuff that can be
158 pointed by the cache.
160 You'll want to grab this in a SharedPtr.
162 JMutexAutoLock * waitCaches()
164 //dstream<<"waitCaches() begin"<<std::endl;
165 JMutexAutoLock waitcachelock(m_waitcache_mutex);
166 JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
167 //dstream<<"waitCaches() end"<<std::endl;
172 // Count of existing caches
174 JMutex m_count_mutex;
175 // This is locked always when there are some caches
176 JMutex m_cache_mutex;
177 // Locked so that when waitCaches() is called, no more caches are created
178 JMutex m_waitcache_mutex;
181 #define MAPTYPE_BASE 0
182 #define MAPTYPE_SERVER 1
183 #define MAPTYPE_CLIENT 2
185 class Map : public NodeContainer, public Heightmappish
189 std::ostream &m_dout;
191 core::map<v2s16, MapSector*> m_sectors;
192 JMutex m_sector_mutex;
194 v3f m_camera_position;
195 v3f m_camera_direction;
196 JMutex m_camera_mutex;
198 // Be sure to set this to NULL when the cached sector is deleted
199 MapSector *m_sector_cache;
200 v2s16 m_sector_cache_p;
202 WrapperHeightmap m_hwrapper;
206 v3s16 drawoffset; // for drawbox()
209 Used by MapBlockPointerCache.
211 waitCaches() can be called to remove all caches before continuing
213 CacheLock m_blockcachelock;
215 Map(std::ostream &dout);
218 virtual u16 nodeContainerId() const
220 return NODECONTAINER_ID_MAP;
223 virtual s32 mapType() const
233 void updateCamera(v3f pos, v3f dir)
235 JMutexAutoLock lock(m_camera_mutex);
236 m_camera_position = pos;
237 m_camera_direction = dir;
240 /*void StartUpdater()
247 updater.setRun(false);
248 while(updater.IsRunning())
252 bool UpdaterIsRunning()
254 return updater.IsRunning();
257 static core::aabbox3d<f32> getNodeBox(v3s16 p)
259 return core::aabbox3d<f32>(
260 (float)p.X * BS - 0.5*BS,
261 (float)p.Y * BS - 0.5*BS,
262 (float)p.Z * BS - 0.5*BS,
263 (float)p.X * BS + 0.5*BS,
264 (float)p.Y * BS + 0.5*BS,
265 (float)p.Z * BS + 0.5*BS
269 //bool sectorExists(v2s16 p);
270 MapSector * getSectorNoGenerate(v2s16 p2d);
272 This is overloaded by ClientMap and ServerMap to allow
273 their differing fetch methods.
275 virtual MapSector * emergeSector(v2s16 p) = 0;
277 // Returns InvalidPositionException if not found
278 MapBlock * getBlockNoCreate(v3s16 p);
279 // Returns NULL if not found
280 MapBlock * getBlockNoCreateNoEx(v3s16 p);
282 // Returns InvalidPositionException if not found
283 f32 getGroundHeight(v2s16 p, bool generate=false);
284 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
286 // Returns InvalidPositionException if not found
287 bool isNodeUnderground(v3s16 p);
289 // virtual from NodeContainer
290 bool isValidPosition(v3s16 p)
292 v3s16 blockpos = getNodeBlockPos(p);
295 blockref = getBlockNoCreate(blockpos);
297 catch(InvalidPositionException &e)
302 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
303 bool is_valid = blockref->isValidPosition(relpos);
307 // virtual from NodeContainer
308 // throws InvalidPositionException if not found
309 MapNode getNode(v3s16 p)
311 v3s16 blockpos = getNodeBlockPos(p);
312 MapBlock * blockref = getBlockNoCreate(blockpos);
313 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
315 return blockref->getNodeNoCheck(relpos);
318 // virtual from NodeContainer
319 // throws InvalidPositionException if not found
320 void setNode(v3s16 p, MapNode & n)
322 v3s16 blockpos = getNodeBlockPos(p);
323 MapBlock * blockref = getBlockNoCreate(blockpos);
324 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
325 blockref->setNodeNoCheck(relpos, n);
328 /*MapNode getNodeGenerate(v3s16 p)
330 v3s16 blockpos = getNodeBlockPos(p);
331 MapBlock * blockref = getBlock(blockpos);
332 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
334 return blockref->getNode(relpos);
337 /*void setNodeGenerate(v3s16 p, MapNode & n)
339 v3s16 blockpos = getNodeBlockPos(p);
340 MapBlock * blockref = getBlock(blockpos);
341 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
342 blockref->setNode(relpos, n);
345 void unspreadLight(enum LightBank bank,
346 core::map<v3s16, u8> & from_nodes,
347 core::map<v3s16, bool> & light_sources,
348 core::map<v3s16, MapBlock*> & modified_blocks);
350 void unLightNeighbors(enum LightBank bank,
351 v3s16 pos, u8 lightwas,
352 core::map<v3s16, bool> & light_sources,
353 core::map<v3s16, MapBlock*> & modified_blocks);
355 void spreadLight(enum LightBank bank,
356 core::map<v3s16, bool> & from_nodes,
357 core::map<v3s16, MapBlock*> & modified_blocks);
359 void lightNeighbors(enum LightBank bank,
361 core::map<v3s16, MapBlock*> & modified_blocks);
363 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
365 s16 propagateSunlight(v3s16 start,
366 core::map<v3s16, MapBlock*> & modified_blocks);
368 void updateLighting(enum LightBank bank,
369 core::map<v3s16, MapBlock*> & a_blocks,
370 core::map<v3s16, MapBlock*> & modified_blocks);
372 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
373 core::map<v3s16, MapBlock*> & modified_blocks);
376 These handle lighting but not faces.
378 void addNodeAndUpdate(v3s16 p, MapNode n,
379 core::map<v3s16, MapBlock*> &modified_blocks);
380 void removeNodeAndUpdate(v3s16 p,
381 core::map<v3s16, MapBlock*> &modified_blocks);
384 void expireMeshes(bool only_daynight_diffed);
387 Updates the faces of the given block and blocks on the
390 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
394 Takes the blocks at the edges into account
396 bool dayNightDiffed(v3s16 blockpos);
398 //core::aabbox3d<s16> getDisplayedBlockArea();
400 //bool updateChangedVisibleArea();
402 virtual void save(bool only_changed){assert(0);};
407 void timerUpdate(float dtime);
409 // Takes cache into account
410 // sector mutex should be locked when calling
411 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
413 // Returns count of deleted sectors
414 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
415 core::list<v3s16> *deleted_blocks=NULL);
417 // For debug printing
418 virtual void PrintInfo(std::ostream &out);
421 // Master heightmap parameters
427 randmax = "constant 70.0";
428 randfactor = "constant 0.6";
429 base = "linear 0 80 0";
433 std::string randfactor;
443 ravines_amount = 1.0;
444 //max_objects_in_block = 30;
447 float ravines_amount;
448 //u16 max_objects_in_block;
451 class ServerMap : public Map
455 savedir: directory to which map data should be saved
457 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
462 return MAPTYPE_SERVER;
466 Forcefully get a sector from somewhere
468 MapSector * emergeSector(v2s16 p);
470 Forcefully get a block from somewhere.
473 - InvalidPositionException: possible if only_from_disk==true
476 - All already existing blocks that were modified are added.
477 - If found on disk, nothing will be added.
478 - If generated, the new block will not be included.
480 lighting_invalidated_blocks:
481 - All blocks that have heavy-to-calculate lighting changes
483 - updateLighting() should be called for these.
485 - A block that is in changed_blocks may not be in
486 lighting_invalidated_blocks.
488 MapBlock * emergeBlock(
491 core::map<v3s16, MapBlock*> &changed_blocks,
492 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
495 void createDir(std::string path);
496 void createSaveDir();
497 // returns something like "xxxxxxxx"
498 std::string getSectorSubDir(v2s16 pos);
499 // returns something like "map/sectors/xxxxxxxx"
500 std::string getSectorDir(v2s16 pos);
501 std::string createSectorDir(v2s16 pos);
502 // dirname: final directory name
503 v2s16 getSectorPos(std::string dirname);
504 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
506 void save(bool only_changed);
509 void saveMasterHeightmap();
510 void loadMasterHeightmap();
512 // The sector mutex should be locked when calling most of these
514 // This only saves sector-specific data such as the heightmap
516 void saveSectorMeta(ServerMapSector *sector);
517 MapSector* loadSectorMeta(std::string dirname);
519 // Full load of a sector including all blocks.
520 // returns true on success, false on failure.
521 bool loadSectorFull(v2s16 p2d);
522 // If sector is not found in memory, try to load it from disk.
523 // Returns true if sector now resides in memory
524 //bool deFlushSector(v2s16 p2d);
526 void saveBlock(MapBlock *block);
527 // This will generate a sector with getSector if not found.
528 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
530 // Gets from master heightmap
531 void getSectorCorners(v2s16 p2d, s16 *corners);
533 // For debug printing
534 virtual void PrintInfo(std::ostream &out);
537 UnlimitedHeightmap *m_heightmap;
540 std::string m_savedir;
541 bool m_map_saving_enabled;
548 class ClientMap : public Map, public scene::ISceneNode
554 s16 &viewing_range_nodes,
555 bool &viewing_range_all,
556 scene::ISceneNode* parent,
557 scene::ISceneManager* mgr,
565 return MAPTYPE_CLIENT;
574 Forcefully get a sector from somewhere
576 MapSector * emergeSector(v2s16 p);
578 void deSerializeSector(v2s16 p2d, std::istream &is);
584 virtual void OnRegisterSceneNode();
586 virtual void render()
588 video::IVideoDriver* driver = SceneManager->getVideoDriver();
589 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
590 renderMap(driver, SceneManager->getSceneNodeRenderPass());
593 virtual const core::aabbox3d<f32>& getBoundingBox() const
598 void renderMap(video::IVideoDriver* driver, s32 pass);
601 Methods for setting temporary modifications to nodes for
603 Return value is position of changed block.
605 v3s16 setTempMod(v3s16 p, NodeMod mod);
606 v3s16 clearTempMod(v3s16 p);
607 // Efficient implementation needs a cache of TempMods
608 //void clearTempMods();
610 // For debug printing
611 virtual void PrintInfo(std::ostream &out);
616 core::aabbox3d<f32> m_box;
618 // This is the master heightmap mesh
622 JMutex &m_range_mutex;
623 s16 &m_viewing_range_nodes;
624 bool &m_viewing_range_all;
629 class MapVoxelManipulator : public VoxelManipulator
632 MapVoxelManipulator(Map *map);
633 virtual ~MapVoxelManipulator();
637 VoxelManipulator::clear();
638 m_loaded_blocks.clear();
641 virtual void emerge(VoxelArea a, s32 caller_id=-1);
643 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
648 NOTE: This might be used or not
650 SUGG: How 'bout an another VoxelManipulator for storing the
651 information about which block is loaded?
653 core::map<v3s16, bool> m_loaded_blocks;