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"
52 m_waitcache_mutex.Init();
57 //dstream<<"cacheCreated() begin"<<std::endl;
58 JMutexAutoLock waitcachelock(m_waitcache_mutex);
59 JMutexAutoLock countlock(m_count_mutex);
61 // If this is the first cache, grab the cache lock
67 //dstream<<"cacheCreated() end"<<std::endl;
72 //dstream<<"cacheRemoved() begin"<<std::endl;
73 JMutexAutoLock countlock(m_count_mutex);
79 // If this is the last one, release the cache lock
81 m_cache_mutex.Unlock();
83 //dstream<<"cacheRemoved() end"<<std::endl;
87 This lock should be taken when removing stuff that can be
90 You'll want to grab this in a SharedPtr.
92 JMutexAutoLock * waitCaches()
94 //dstream<<"waitCaches() begin"<<std::endl;
95 JMutexAutoLock waitcachelock(m_waitcache_mutex);
96 JMutexAutoLock *lock = new JMutexAutoLock(m_cache_mutex);
97 //dstream<<"waitCaches() end"<<std::endl;
102 // Count of existing caches
104 JMutex m_count_mutex;
105 // This is locked always when there are some caches
106 JMutex m_cache_mutex;
107 // Locked so that when waitCaches() is called, no more caches are created
108 JMutex m_waitcache_mutex;
111 #define MAPTYPE_BASE 0
112 #define MAPTYPE_SERVER 1
113 #define MAPTYPE_CLIENT 2
115 class Map : public NodeContainer, public Heightmappish
119 std::ostream &m_dout;
121 core::map<v2s16, MapSector*> m_sectors;
122 JMutex m_sector_mutex;
124 v3f m_camera_position;
125 v3f m_camera_direction;
126 JMutex m_camera_mutex;
128 // Be sure to set this to NULL when the cached sector is deleted
129 MapSector *m_sector_cache;
130 v2s16 m_sector_cache_p;
132 WrapperHeightmap m_hwrapper;
136 v3s16 drawoffset; // for drawbox()
139 Used by MapBlockPointerCache.
141 waitCaches() can be called to remove all caches before continuing
143 TODO: Remove this, MapBlockPointerCache doesn't exist anymore,
144 because it doesn't give any speed benefits
146 CacheLock m_blockcachelock;
148 Map(std::ostream &dout);
151 virtual u16 nodeContainerId() const
153 return NODECONTAINER_ID_MAP;
156 virtual s32 mapType() const
166 void updateCamera(v3f pos, v3f dir)
168 JMutexAutoLock lock(m_camera_mutex);
169 m_camera_position = pos;
170 m_camera_direction = dir;
173 /*void StartUpdater()
180 updater.setRun(false);
181 while(updater.IsRunning())
185 bool UpdaterIsRunning()
187 return updater.IsRunning();
190 static core::aabbox3d<f32> getNodeBox(v3s16 p)
192 return core::aabbox3d<f32>(
193 (float)p.X * BS - 0.5*BS,
194 (float)p.Y * BS - 0.5*BS,
195 (float)p.Z * BS - 0.5*BS,
196 (float)p.X * BS + 0.5*BS,
197 (float)p.Y * BS + 0.5*BS,
198 (float)p.Z * BS + 0.5*BS
202 //bool sectorExists(v2s16 p);
203 MapSector * getSectorNoGenerate(v2s16 p2d);
205 This is overloaded by ClientMap and ServerMap to allow
206 their differing fetch methods.
208 virtual MapSector * emergeSector(v2s16 p) = 0;
210 // Returns InvalidPositionException if not found
211 MapBlock * getBlockNoCreate(v3s16 p);
212 // Returns NULL if not found
213 MapBlock * getBlockNoCreateNoEx(v3s16 p);
215 // Returns InvalidPositionException if not found
216 f32 getGroundHeight(v2s16 p, bool generate=false);
217 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
219 // Returns InvalidPositionException if not found
220 bool isNodeUnderground(v3s16 p);
222 // virtual from NodeContainer
223 bool isValidPosition(v3s16 p)
225 v3s16 blockpos = getNodeBlockPos(p);
228 blockref = getBlockNoCreate(blockpos);
230 catch(InvalidPositionException &e)
235 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
236 bool is_valid = blockref->isValidPosition(relpos);
240 // virtual from NodeContainer
241 // throws InvalidPositionException if not found
242 MapNode getNode(v3s16 p)
244 v3s16 blockpos = getNodeBlockPos(p);
245 MapBlock * blockref = getBlockNoCreate(blockpos);
246 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
248 return blockref->getNodeNoCheck(relpos);
251 // virtual from NodeContainer
252 // throws InvalidPositionException if not found
253 void setNode(v3s16 p, MapNode & n)
255 v3s16 blockpos = getNodeBlockPos(p);
256 MapBlock * blockref = getBlockNoCreate(blockpos);
257 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
258 blockref->setNodeNoCheck(relpos, n);
261 /*MapNode getNodeGenerate(v3s16 p)
263 v3s16 blockpos = getNodeBlockPos(p);
264 MapBlock * blockref = getBlock(blockpos);
265 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
267 return blockref->getNode(relpos);
270 /*void setNodeGenerate(v3s16 p, MapNode & n)
272 v3s16 blockpos = getNodeBlockPos(p);
273 MapBlock * blockref = getBlock(blockpos);
274 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
275 blockref->setNode(relpos, n);
278 void unspreadLight(enum LightBank bank,
279 core::map<v3s16, u8> & from_nodes,
280 core::map<v3s16, bool> & light_sources,
281 core::map<v3s16, MapBlock*> & modified_blocks);
283 void unLightNeighbors(enum LightBank bank,
284 v3s16 pos, u8 lightwas,
285 core::map<v3s16, bool> & light_sources,
286 core::map<v3s16, MapBlock*> & modified_blocks);
288 void spreadLight(enum LightBank bank,
289 core::map<v3s16, bool> & from_nodes,
290 core::map<v3s16, MapBlock*> & modified_blocks);
292 void lightNeighbors(enum LightBank bank,
294 core::map<v3s16, MapBlock*> & modified_blocks);
296 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
298 s16 propagateSunlight(v3s16 start,
299 core::map<v3s16, MapBlock*> & modified_blocks);
301 void updateLighting(enum LightBank bank,
302 core::map<v3s16, MapBlock*> & a_blocks,
303 core::map<v3s16, MapBlock*> & modified_blocks);
305 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
306 core::map<v3s16, MapBlock*> & modified_blocks);
309 These handle lighting but not faces.
311 void addNodeAndUpdate(v3s16 p, MapNode n,
312 core::map<v3s16, MapBlock*> &modified_blocks);
313 void removeNodeAndUpdate(v3s16 p,
314 core::map<v3s16, MapBlock*> &modified_blocks);
317 void expireMeshes(bool only_daynight_diffed);
320 Updates the faces of the given block and blocks on the
323 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
327 Takes the blocks at the edges into account
329 bool dayNightDiffed(v3s16 blockpos);
331 //core::aabbox3d<s16> getDisplayedBlockArea();
333 //bool updateChangedVisibleArea();
335 virtual void save(bool only_changed){assert(0);};
340 void timerUpdate(float dtime);
342 // Takes cache into account
343 // sector mutex should be locked when calling
344 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
346 // Returns count of deleted sectors
347 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
348 core::list<v3s16> *deleted_blocks=NULL);
350 // For debug printing
351 virtual void PrintInfo(std::ostream &out);
354 // Master heightmap parameters
360 randmax = "constant 70.0";
361 randfactor = "constant 0.6";
362 base = "linear 0 80 0";
366 std::string randfactor;
376 ravines_amount = 1.0;
377 //max_objects_in_block = 30;
380 float ravines_amount;
381 //u16 max_objects_in_block;
384 class ServerMap : public Map
388 savedir: directory to which map data should be saved
390 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
395 return MAPTYPE_SERVER;
399 Forcefully get a sector from somewhere
401 MapSector * emergeSector(v2s16 p);
403 Forcefully get a block from somewhere.
406 - InvalidPositionException: possible if only_from_disk==true
409 - All already existing blocks that were modified are added.
410 - If found on disk, nothing will be added.
411 - If generated, the new block will not be included.
413 lighting_invalidated_blocks:
414 - All blocks that have heavy-to-calculate lighting changes
416 - updateLighting() should be called for these.
418 - A block that is in changed_blocks may not be in
419 lighting_invalidated_blocks.
421 MapBlock * emergeBlock(
424 core::map<v3s16, MapBlock*> &changed_blocks,
425 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
428 void createDir(std::string path);
429 void createSaveDir();
430 // returns something like "xxxxxxxx"
431 std::string getSectorSubDir(v2s16 pos);
432 // returns something like "map/sectors/xxxxxxxx"
433 std::string getSectorDir(v2s16 pos);
434 std::string createSectorDir(v2s16 pos);
435 // dirname: final directory name
436 v2s16 getSectorPos(std::string dirname);
437 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
439 void save(bool only_changed);
442 void saveMasterHeightmap();
443 void loadMasterHeightmap();
445 // The sector mutex should be locked when calling most of these
447 // This only saves sector-specific data such as the heightmap
449 void saveSectorMeta(ServerMapSector *sector);
450 MapSector* loadSectorMeta(std::string dirname);
452 // Full load of a sector including all blocks.
453 // returns true on success, false on failure.
454 bool loadSectorFull(v2s16 p2d);
455 // If sector is not found in memory, try to load it from disk.
456 // Returns true if sector now resides in memory
457 //bool deFlushSector(v2s16 p2d);
459 void saveBlock(MapBlock *block);
460 // This will generate a sector with getSector if not found.
461 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
463 // Gets from master heightmap
464 void getSectorCorners(v2s16 p2d, s16 *corners);
466 // For debug printing
467 virtual void PrintInfo(std::ostream &out);
470 UnlimitedHeightmap *m_heightmap;
473 std::string m_savedir;
474 bool m_map_saving_enabled;
479 struct MapDrawControl
484 wanted_max_blocks(0),
487 blocks_would_have_drawn(0)
490 // Overrides limits by drawing everything
492 // Wanted drawing range
494 // Maximum number of blocks to draw
495 u32 wanted_max_blocks;
496 // Blocks in this range are drawn regardless of number of blocks drawn
497 float wanted_min_range;
498 // Number of blocks rendered is written here by the renderer
500 // Number of blocks that would have been drawn in wanted_range
501 u32 blocks_would_have_drawn;
506 class ClientMap : public Map, public scene::ISceneNode
511 MapDrawControl &control,
512 scene::ISceneNode* parent,
513 scene::ISceneManager* mgr,
521 return MAPTYPE_CLIENT;
530 Forcefully get a sector from somewhere
532 MapSector * emergeSector(v2s16 p);
534 void deSerializeSector(v2s16 p2d, std::istream &is);
540 virtual void OnRegisterSceneNode();
542 virtual void render()
544 video::IVideoDriver* driver = SceneManager->getVideoDriver();
545 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
546 renderMap(driver, SceneManager->getSceneNodeRenderPass());
549 virtual const core::aabbox3d<f32>& getBoundingBox() const
554 void renderMap(video::IVideoDriver* driver, s32 pass);
557 Methods for setting temporary modifications to nodes for
559 Return value is position of changed block.
561 v3s16 setTempMod(v3s16 p, NodeMod mod);
562 v3s16 clearTempMod(v3s16 p);
563 // Efficient implementation needs a cache of TempMods
564 //void clearTempMods();
566 // For debug printing
567 virtual void PrintInfo(std::ostream &out);
572 core::aabbox3d<f32> m_box;
574 // This is the master heightmap mesh
578 MapDrawControl &m_control;
583 class MapVoxelManipulator : public VoxelManipulator
586 MapVoxelManipulator(Map *map);
587 virtual ~MapVoxelManipulator();
591 VoxelManipulator::clear();
592 m_loaded_blocks.clear();
595 virtual void emerge(VoxelArea a, s32 caller_id=-1);
597 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
602 NOTE: This might be used or not
604 SUGG: How 'bout an another VoxelManipulator for storing the
605 information about which block is loaded?
607 core::map<v3s16, bool> m_loaded_blocks;