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"
29 class InvalidFilenameException : public BaseException
32 InvalidFilenameException(const char *s):
37 #define MAPTYPE_BASE 0
38 #define MAPTYPE_SERVER 1
39 #define MAPTYPE_CLIENT 2
41 class Map : public NodeContainer, public Heightmappish
47 core::map<v2s16, MapSector*> m_sectors;
48 JMutex m_sector_mutex;
50 v3f m_camera_position;
51 v3f m_camera_direction;
52 JMutex m_camera_mutex;
54 // Be sure to set this to NULL when the cached sector is deleted
55 MapSector *m_sector_cache;
56 v2s16 m_sector_cache_p;
58 WrapperHeightmap m_hwrapper;
62 v3s16 drawoffset; // for drawbox()
64 Map(std::ostream &dout);
67 virtual u16 nodeContainerId() const
69 return NODECONTAINER_ID_MAP;
72 virtual s32 mapType() const
77 void updateCamera(v3f pos, v3f dir)
79 JMutexAutoLock lock(m_camera_mutex);
80 m_camera_position = pos;
81 m_camera_direction = dir;
91 updater.setRun(false);
92 while(updater.IsRunning())
96 bool UpdaterIsRunning()
98 return updater.IsRunning();
101 static core::aabbox3d<f32> getNodeBox(v3s16 p)
103 return core::aabbox3d<f32>(
104 (float)p.X * BS - 0.5*BS,
105 (float)p.Y * BS - 0.5*BS,
106 (float)p.Z * BS - 0.5*BS,
107 (float)p.X * BS + 0.5*BS,
108 (float)p.Y * BS + 0.5*BS,
109 (float)p.Z * BS + 0.5*BS
113 //bool sectorExists(v2s16 p);
114 MapSector * getSectorNoGenerate(v2s16 p2d);
116 This is overloaded by ClientMap and ServerMap to allow
117 their differing fetch methods.
119 virtual MapSector * emergeSector(v2s16 p) = 0;
121 // Returns InvalidPositionException if not found
122 MapBlock * getBlockNoCreate(v3s16 p);
123 //virtual MapBlock * getBlock(v3s16 p, bool generate=true);
125 // Returns InvalidPositionException if not found
126 f32 getGroundHeight(v2s16 p, bool generate=false);
127 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
129 // Returns InvalidPositionException if not found
130 bool isNodeUnderground(v3s16 p);
132 // virtual from NodeContainer
133 bool isValidPosition(v3s16 p)
135 v3s16 blockpos = getNodeBlockPos(p);
138 blockref = getBlockNoCreate(blockpos);
140 catch(InvalidPositionException &e)
145 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
146 bool is_valid = blockref->isValidPosition(relpos);
150 // virtual from NodeContainer
151 MapNode getNode(v3s16 p)
153 v3s16 blockpos = getNodeBlockPos(p);
154 MapBlock * blockref = getBlockNoCreate(blockpos);
155 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
157 return blockref->getNode(relpos);
160 // virtual from NodeContainer
161 void setNode(v3s16 p, MapNode & n)
163 v3s16 blockpos = getNodeBlockPos(p);
164 MapBlock * blockref = getBlockNoCreate(blockpos);
165 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
166 blockref->setNode(relpos, n);
169 /*MapNode getNodeGenerate(v3s16 p)
171 v3s16 blockpos = getNodeBlockPos(p);
172 MapBlock * blockref = getBlock(blockpos);
173 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
175 return blockref->getNode(relpos);
178 /*void setNodeGenerate(v3s16 p, MapNode & n)
180 v3s16 blockpos = getNodeBlockPos(p);
181 MapBlock * blockref = getBlock(blockpos);
182 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
183 blockref->setNode(relpos, n);
186 void unspreadLight(core::map<v3s16, u8> & from_nodes,
187 core::map<v3s16, bool> & light_sources,
188 core::map<v3s16, MapBlock*> & modified_blocks);
190 void unLightNeighbors(v3s16 pos, u8 lightwas,
191 core::map<v3s16, bool> & light_sources,
192 core::map<v3s16, MapBlock*> & modified_blocks);
194 void spreadLight(core::map<v3s16, bool> & from_nodes,
195 core::map<v3s16, MapBlock*> & modified_blocks);
197 void lightNeighbors(v3s16 pos,
198 core::map<v3s16, MapBlock*> & modified_blocks);
200 v3s16 getBrightestNeighbour(v3s16 p);
202 s16 propagateSunlight(v3s16 start,
203 core::map<v3s16, MapBlock*> & modified_blocks);
205 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
206 core::map<v3s16, MapBlock*> & modified_blocks);
209 These handle lighting but not faces.
211 void addNodeAndUpdate(v3s16 p, MapNode n,
212 core::map<v3s16, MapBlock*> &modified_blocks);
213 void removeNodeAndUpdate(v3s16 p,
214 core::map<v3s16, MapBlock*> &modified_blocks);
217 Updates the faces of the given block and blocks on the
220 void updateMeshes(v3s16 blockpos);
222 //core::aabbox3d<s16> getDisplayedBlockArea();
224 //bool updateChangedVisibleArea();
226 virtual void save(bool only_changed){assert(0);};
231 void timerUpdate(float dtime);
233 // Takes cache into account
234 // sector mutex should be locked when calling
235 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
237 // Returns count of deleted sectors
238 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
239 core::list<v3s16> *deleted_blocks=NULL);
241 // For debug printing
242 virtual void PrintInfo(std::ostream &out);
245 // Master heightmap parameters
250 heightmap_blocksize = 64;
251 height_randmax = "constant 70.0";
252 height_randfactor = "constant 0.6";
253 height_base = "linear 0 80 0";
255 s16 heightmap_blocksize;
256 std::string height_randmax;
257 std::string height_randfactor;
258 std::string height_base;
267 //max_objects_in_block = 30;
270 //u16 max_objects_in_block;
273 class ServerMap : public Map
277 savedir: directory to which map data should be saved
279 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
284 return MAPTYPE_SERVER;
288 Forcefully get a sector from somewhere
290 MapSector * emergeSector(v2s16 p);
292 Forcefully get a block from somewhere.
295 - InvalidPositionException: possible if only_from_disk==true
298 - All already existing blocks that were modified are added.
299 - If found on disk, nothing will be added.
300 - If generated, the new block will not be included.
302 lighting_invalidated_blocks:
303 - All blocks that have heavy-to-calculate lighting changes
305 - updateLighting() should be called for these.
307 - A block that is in changed_blocks may not be in
308 lighting_invalidated_blocks.
310 MapBlock * emergeBlock(
313 core::map<v3s16, MapBlock*> &changed_blocks,
314 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
317 void createDir(std::string path);
318 void createSaveDir();
319 // returns something like "xxxxxxxx"
320 std::string getSectorSubDir(v2s16 pos);
321 // returns something like "map/sectors/xxxxxxxx"
322 std::string getSectorDir(v2s16 pos);
323 std::string createSectorDir(v2s16 pos);
324 // dirname: final directory name
325 v2s16 getSectorPos(std::string dirname);
326 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
328 void save(bool only_changed);
331 void saveMasterHeightmap();
332 void loadMasterHeightmap();
334 // The sector mutex should be locked when calling most of these
336 // This only saves sector-specific data such as the heightmap
338 void saveSectorMeta(ServerMapSector *sector);
339 MapSector* loadSectorMeta(std::string dirname);
341 // Full load of a sector including all blocks.
342 // returns true on success, false on failure.
343 bool loadSectorFull(v2s16 p2d);
344 // If sector is not found in memory, try to load it from disk.
345 // Returns true if sector now resides in memory
346 //bool deFlushSector(v2s16 p2d);
348 void saveBlock(MapBlock *block);
349 // This will generate a sector with getSector if not found.
350 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
352 // Gets from master heightmap
353 void getSectorCorners(v2s16 p2d, s16 *corners);
355 // For debug printing
356 virtual void PrintInfo(std::ostream &out);
359 UnlimitedHeightmap *m_heightmap;
362 std::string m_savedir;
363 bool m_map_saving_enabled;
368 class ClientMap : public Map, public scene::ISceneNode
373 video::SMaterial *materials,
374 scene::ISceneNode* parent,
375 scene::ISceneManager* mgr,
383 return MAPTYPE_CLIENT;
387 Forcefully get a sector from somewhere
389 MapSector * emergeSector(v2s16 p);
391 void deSerializeSector(v2s16 p2d, std::istream &is);
397 virtual void OnRegisterSceneNode()
401 //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
402 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
403 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
406 ISceneNode::OnRegisterSceneNode();
409 virtual void render()
411 video::IVideoDriver* driver = SceneManager->getVideoDriver();
412 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
413 renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass());
416 virtual const core::aabbox3d<f32>& getBoundingBox() const
421 void renderMap(video::IVideoDriver* driver,
422 video::SMaterial *materials, s32 pass);
424 // Update master heightmap mesh
427 // For debug printing
428 virtual void PrintInfo(std::ostream &out);
433 video::SMaterial *m_materials;
435 core::aabbox3d<f32> m_box;
437 // This is the master heightmap mesh