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"
44 #define MAPTYPE_BASE 0
45 #define MAPTYPE_SERVER 1
46 #define MAPTYPE_CLIENT 2
48 class Map : public NodeContainer, public Heightmappish
52 Map(std::ostream &dout);
55 virtual u16 nodeContainerId() const
57 return NODECONTAINER_ID_MAP;
60 virtual s32 mapType() const
70 void updateCamera(v3f pos, v3f dir)
72 JMutexAutoLock lock(m_camera_mutex);
73 m_camera_position = pos;
74 m_camera_direction = dir;
77 static core::aabbox3d<f32> getNodeBox(v3s16 p)
79 return core::aabbox3d<f32>(
80 (float)p.X * BS - 0.5*BS,
81 (float)p.Y * BS - 0.5*BS,
82 (float)p.Z * BS - 0.5*BS,
83 (float)p.X * BS + 0.5*BS,
84 (float)p.Y * BS + 0.5*BS,
85 (float)p.Z * BS + 0.5*BS
89 //bool sectorExists(v2s16 p);
90 MapSector * getSectorNoGenerate(v2s16 p2d);
92 This is overloaded by ClientMap and ServerMap to allow
93 their differing fetch methods.
95 virtual MapSector * emergeSector(v2s16 p) = 0;
97 // Returns InvalidPositionException if not found
98 MapBlock * getBlockNoCreate(v3s16 p);
99 // Returns NULL if not found
100 MapBlock * getBlockNoCreateNoEx(v3s16 p);
102 // Returns InvalidPositionException if not found
103 f32 getGroundHeight(v2s16 p, bool generate=false);
104 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
106 // Returns InvalidPositionException if not found
107 bool isNodeUnderground(v3s16 p);
109 // virtual from NodeContainer
110 bool isValidPosition(v3s16 p)
112 v3s16 blockpos = getNodeBlockPos(p);
115 blockref = getBlockNoCreate(blockpos);
117 catch(InvalidPositionException &e)
122 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
123 bool is_valid = blockref->isValidPosition(relpos);
127 // virtual from NodeContainer
128 // throws InvalidPositionException if not found
129 MapNode getNode(v3s16 p)
131 v3s16 blockpos = getNodeBlockPos(p);
132 MapBlock * blockref = getBlockNoCreate(blockpos);
133 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
135 return blockref->getNodeNoCheck(relpos);
138 // virtual from NodeContainer
139 // throws InvalidPositionException if not found
140 void setNode(v3s16 p, MapNode & n)
142 v3s16 blockpos = getNodeBlockPos(p);
143 MapBlock * blockref = getBlockNoCreate(blockpos);
144 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
145 blockref->setNodeNoCheck(relpos, n);
148 /*MapNode getNodeGenerate(v3s16 p)
150 v3s16 blockpos = getNodeBlockPos(p);
151 MapBlock * blockref = getBlock(blockpos);
152 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
154 return blockref->getNode(relpos);
157 /*void setNodeGenerate(v3s16 p, MapNode & n)
159 v3s16 blockpos = getNodeBlockPos(p);
160 MapBlock * blockref = getBlock(blockpos);
161 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
162 blockref->setNode(relpos, n);
165 void unspreadLight(enum LightBank bank,
166 core::map<v3s16, u8> & from_nodes,
167 core::map<v3s16, bool> & light_sources,
168 core::map<v3s16, MapBlock*> & modified_blocks);
170 void unLightNeighbors(enum LightBank bank,
171 v3s16 pos, u8 lightwas,
172 core::map<v3s16, bool> & light_sources,
173 core::map<v3s16, MapBlock*> & modified_blocks);
175 void spreadLight(enum LightBank bank,
176 core::map<v3s16, bool> & from_nodes,
177 core::map<v3s16, MapBlock*> & modified_blocks);
179 void lightNeighbors(enum LightBank bank,
181 core::map<v3s16, MapBlock*> & modified_blocks);
183 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
185 s16 propagateSunlight(v3s16 start,
186 core::map<v3s16, MapBlock*> & modified_blocks);
188 void updateLighting(enum LightBank bank,
189 core::map<v3s16, MapBlock*> & a_blocks,
190 core::map<v3s16, MapBlock*> & modified_blocks);
192 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
193 core::map<v3s16, MapBlock*> & modified_blocks);
196 These handle lighting but not faces.
198 void addNodeAndUpdate(v3s16 p, MapNode n,
199 core::map<v3s16, MapBlock*> &modified_blocks);
200 void removeNodeAndUpdate(v3s16 p,
201 core::map<v3s16, MapBlock*> &modified_blocks);
204 void expireMeshes(bool only_daynight_diffed);
207 Updates the faces of the given block and blocks on the
210 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
214 Takes the blocks at the edges into account
216 bool dayNightDiffed(v3s16 blockpos);
218 //core::aabbox3d<s16> getDisplayedBlockArea();
220 //bool updateChangedVisibleArea();
222 virtual void save(bool only_changed){assert(0);};
227 void timerUpdate(float dtime);
229 // Takes cache into account
230 // sector mutex should be locked when calling
231 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
233 // Returns count of deleted sectors
234 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
235 core::list<v3s16> *deleted_blocks=NULL);
237 // For debug printing
238 virtual void PrintInfo(std::ostream &out);
240 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
248 std::ostream &m_dout;
250 core::map<v2s16, MapSector*> m_sectors;
251 JMutex m_sector_mutex;
253 v3f m_camera_position;
254 v3f m_camera_direction;
255 JMutex m_camera_mutex;
257 // Be sure to set this to NULL when the cached sector is deleted
258 MapSector *m_sector_cache;
259 v2s16 m_sector_cache_p;
261 WrapperHeightmap m_hwrapper;
263 // Queued transforming water nodes
264 UniqueQueue<v3s16> m_transforming_liquid;
267 // Master heightmap parameters
273 randmax = "constant 70.0";
274 randfactor = "constant 0.6";
275 base = "linear 0 80 0";
279 std::string randfactor;
289 ravines_amount = 1.0;
290 //max_objects_in_block = 30;
293 float ravines_amount;
294 //u16 max_objects_in_block;
300 This is the only map class that is able to generate map.
303 class ServerMap : public Map
307 savedir: directory to which map data should be saved
309 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
314 return MAPTYPE_SERVER;
318 Forcefully get a sector from somewhere
320 MapSector * emergeSector(v2s16 p);
322 Forcefully get a block from somewhere.
325 - InvalidPositionException: possible if only_from_disk==true
328 - All already existing blocks that were modified are added.
329 - If found on disk, nothing will be added.
330 - If generated, the new block will not be included.
332 lighting_invalidated_blocks:
333 - All blocks that have heavy-to-calculate lighting changes
335 - updateLighting() should be called for these.
337 - A block that is in changed_blocks may not be in
338 lighting_invalidated_blocks.
340 MapBlock * emergeBlock(
343 core::map<v3s16, MapBlock*> &changed_blocks,
344 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
347 void createDir(std::string path);
348 void createSaveDir();
349 // returns something like "xxxxxxxx"
350 std::string getSectorSubDir(v2s16 pos);
351 // returns something like "map/sectors/xxxxxxxx"
352 std::string getSectorDir(v2s16 pos);
353 std::string createSectorDir(v2s16 pos);
354 // dirname: final directory name
355 v2s16 getSectorPos(std::string dirname);
356 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
358 void save(bool only_changed);
361 void saveMasterHeightmap();
362 void loadMasterHeightmap();
364 // The sector mutex should be locked when calling most of these
366 // This only saves sector-specific data such as the heightmap
368 void saveSectorMeta(ServerMapSector *sector);
369 MapSector* loadSectorMeta(std::string dirname);
371 // Full load of a sector including all blocks.
372 // returns true on success, false on failure.
373 bool loadSectorFull(v2s16 p2d);
374 // If sector is not found in memory, try to load it from disk.
375 // Returns true if sector now resides in memory
376 //bool deFlushSector(v2s16 p2d);
378 void saveBlock(MapBlock *block);
379 // This will generate a sector with getSector if not found.
380 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
382 // Gets from master heightmap
383 void getSectorCorners(v2s16 p2d, s16 *corners);
385 // For debug printing
386 virtual void PrintInfo(std::ostream &out);
389 // Generator parameters
390 UnlimitedHeightmap *m_heightmap;
392 PointAttributeDatabase m_padb;
394 std::string m_savedir;
395 bool m_map_saving_enabled;
400 struct MapDrawControl
405 wanted_max_blocks(0),
408 blocks_would_have_drawn(0)
411 // Overrides limits by drawing everything
413 // Wanted drawing range
415 // Maximum number of blocks to draw
416 u32 wanted_max_blocks;
417 // Blocks in this range are drawn regardless of number of blocks drawn
418 float wanted_min_range;
419 // Number of blocks rendered is written here by the renderer
421 // Number of blocks that would have been drawn in wanted_range
422 u32 blocks_would_have_drawn;
430 This is the only map class that is able to render itself on screen.
433 class ClientMap : public Map, public scene::ISceneNode
438 MapDrawControl &control,
439 scene::ISceneNode* parent,
440 scene::ISceneManager* mgr,
448 return MAPTYPE_CLIENT;
457 Forcefully get a sector from somewhere
459 MapSector * emergeSector(v2s16 p);
461 void deSerializeSector(v2s16 p2d, std::istream &is);
467 virtual void OnRegisterSceneNode();
469 virtual void render()
471 video::IVideoDriver* driver = SceneManager->getVideoDriver();
472 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
473 renderMap(driver, SceneManager->getSceneNodeRenderPass());
476 virtual const core::aabbox3d<f32>& getBoundingBox() const
481 void renderMap(video::IVideoDriver* driver, s32 pass);
484 Methods for setting temporary modifications to nodes for
486 Return value is position of changed block.
488 v3s16 setTempMod(v3s16 p, NodeMod mod, bool *changed=NULL);
489 v3s16 clearTempMod(v3s16 p, bool *changed=NULL);
490 // Efficient implementation needs a cache of TempMods
491 //void clearTempMods();
493 // For debug printing
494 virtual void PrintInfo(std::ostream &out);
499 core::aabbox3d<f32> m_box;
501 // This is the master heightmap mesh
505 MapDrawControl &m_control;
510 class MapVoxelManipulator : public VoxelManipulator
513 MapVoxelManipulator(Map *map);
514 virtual ~MapVoxelManipulator();
518 VoxelManipulator::clear();
519 m_loaded_blocks.clear();
522 virtual void emerge(VoxelArea a, s32 caller_id=-1);
524 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
529 NOTE: This might be used or not
531 SUGG: How 'bout an another VoxelManipulator for storing the
532 information about which block is loaded?
534 core::map<v3s16, bool> m_loaded_blocks;
537 class ManualMapVoxelManipulator : public MapVoxelManipulator
540 ManualMapVoxelManipulator(Map *map);
541 virtual ~ManualMapVoxelManipulator();
543 virtual void emerge(VoxelArea a, s32 caller_id=-1);
545 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);