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);
249 heightmap_blocksize = 64;
250 height_randmax = "constant 70.0";
251 height_randfactor = "constant 0.6";
252 height_base = "linear 0 80 0";
253 plants_amount = "1.0";
255 s16 heightmap_blocksize;
256 std::string height_randmax;
257 std::string height_randfactor;
258 std::string height_base;
259 std::string plants_amount;
262 class ServerMap : public Map
266 savedir: directory to which map data should be saved
268 ServerMap(std::string savedir, MapgenParams params);
273 return MAPTYPE_SERVER;
277 Forcefully get a sector from somewhere
279 MapSector * emergeSector(v2s16 p);
281 Forcefully get a block from somewhere.
284 - InvalidPositionException: possible if only_from_disk==true
287 - All already existing blocks that were modified are added.
288 - If found on disk, nothing will be added.
289 - If generated, the new block will not be included.
291 lighting_invalidated_blocks:
292 - All blocks that have heavy-to-calculate lighting changes
294 - updateLighting() should be called for these.
296 - A block that is in changed_blocks may not be in
297 lighting_invalidated_blocks.
299 MapBlock * emergeBlock(
302 core::map<v3s16, MapBlock*> &changed_blocks,
303 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
306 void createDir(std::string path);
307 void createSaveDir();
308 // returns something like "xxxxxxxx"
309 std::string getSectorSubDir(v2s16 pos);
310 // returns something like "map/sectors/xxxxxxxx"
311 std::string getSectorDir(v2s16 pos);
312 std::string createSectorDir(v2s16 pos);
313 // dirname: final directory name
314 v2s16 getSectorPos(std::string dirname);
315 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
317 void save(bool only_changed);
320 void saveMasterHeightmap();
321 void loadMasterHeightmap();
323 // The sector mutex should be locked when calling most of these
325 // This only saves sector-specific data such as the heightmap
327 void saveSectorMeta(ServerMapSector *sector);
328 MapSector* loadSectorMeta(std::string dirname);
330 // Full load of a sector including all blocks.
331 // returns true on success, false on failure.
332 bool loadSectorFull(v2s16 p2d);
333 // If sector is not found in memory, try to load it from disk.
334 // Returns true if sector now resides in memory
335 //bool deFlushSector(v2s16 p2d);
337 void saveBlock(MapBlock *block);
338 // This will generate a sector with getSector if not found.
339 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
341 // Gets from master heightmap
342 void getSectorCorners(v2s16 p2d, s16 *corners);
344 // For debug printing
345 virtual void PrintInfo(std::ostream &out);
348 UnlimitedHeightmap *m_heightmap;
349 std::string m_savedir;
350 bool m_map_saving_enabled;
355 class ClientMap : public Map, public scene::ISceneNode
360 video::SMaterial *materials,
361 scene::ISceneNode* parent,
362 scene::ISceneManager* mgr,
370 return MAPTYPE_CLIENT;
374 Forcefully get a sector from somewhere
376 MapSector * emergeSector(v2s16 p);
378 void deSerializeSector(v2s16 p2d, std::istream &is);
384 virtual void OnRegisterSceneNode()
388 //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX);
389 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
390 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
393 ISceneNode::OnRegisterSceneNode();
396 virtual void render()
398 video::IVideoDriver* driver = SceneManager->getVideoDriver();
399 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
400 renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass());
403 virtual const core::aabbox3d<f32>& getBoundingBox() const
408 void renderMap(video::IVideoDriver* driver,
409 video::SMaterial *materials, s32 pass);
411 // Update master heightmap mesh
414 // For debug printing
415 virtual void PrintInfo(std::ostream &out);
420 video::SMaterial *m_materials;
422 core::aabbox3d<f32> m_box;
424 // This is the master heightmap mesh