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 Update the faces of the given block and blocks on the
210 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
212 // Update meshes that touch the node
213 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
217 Takes the blocks at the edges into account
219 bool dayNightDiffed(v3s16 blockpos);
221 //core::aabbox3d<s16> getDisplayedBlockArea();
223 //bool updateChangedVisibleArea();
225 virtual void save(bool only_changed){assert(0);};
230 void timerUpdate(float dtime);
232 // Takes cache into account
233 // sector mutex should be locked when calling
234 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
236 // Returns count of deleted sectors
237 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
238 core::list<v3s16> *deleted_blocks=NULL);
240 // For debug printing
241 virtual void PrintInfo(std::ostream &out);
243 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
251 std::ostream &m_dout;
253 core::map<v2s16, MapSector*> m_sectors;
254 JMutex m_sector_mutex;
256 v3f m_camera_position;
257 v3f m_camera_direction;
258 JMutex m_camera_mutex;
260 // Be sure to set this to NULL when the cached sector is deleted
261 MapSector *m_sector_cache;
262 v2s16 m_sector_cache_p;
264 WrapperHeightmap m_hwrapper;
266 // Queued transforming water nodes
267 UniqueQueue<v3s16> m_transforming_liquid;
270 // Master heightmap parameters
276 randmax = "constant 70.0";
277 randfactor = "constant 0.6";
278 base = "linear 0 80 0";
282 std::string randfactor;
292 ravines_amount = 1.0;
293 //max_objects_in_block = 30;
296 float ravines_amount;
297 //u16 max_objects_in_block;
303 This is the only map class that is able to generate map.
306 class ServerMap : public Map
310 savedir: directory to which map data should be saved
312 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
317 return MAPTYPE_SERVER;
321 Forcefully get a sector from somewhere
323 MapSector * emergeSector(v2s16 p);
325 Forcefully get a block from somewhere.
328 - InvalidPositionException: possible if only_from_disk==true
331 - All already existing blocks that were modified are added.
332 - If found on disk, nothing will be added.
333 - If generated, the new block will not be included.
335 lighting_invalidated_blocks:
336 - All blocks that have heavy-to-calculate lighting changes
338 - updateLighting() should be called for these.
340 - A block that is in changed_blocks may not be in
341 lighting_invalidated_blocks.
343 MapBlock * emergeBlock(
346 core::map<v3s16, MapBlock*> &changed_blocks,
347 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
350 void createDir(std::string path);
351 void createSaveDir();
352 // returns something like "xxxxxxxx"
353 std::string getSectorSubDir(v2s16 pos);
354 // returns something like "map/sectors/xxxxxxxx"
355 std::string getSectorDir(v2s16 pos);
356 std::string createSectorDir(v2s16 pos);
357 // dirname: final directory name
358 v2s16 getSectorPos(std::string dirname);
359 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
361 void save(bool only_changed);
364 void saveMasterHeightmap();
365 void loadMasterHeightmap();
367 // The sector mutex should be locked when calling most of these
369 // This only saves sector-specific data such as the heightmap
371 void saveSectorMeta(ServerMapSector *sector);
372 MapSector* loadSectorMeta(std::string dirname);
374 // Full load of a sector including all blocks.
375 // returns true on success, false on failure.
376 bool loadSectorFull(v2s16 p2d);
377 // If sector is not found in memory, try to load it from disk.
378 // Returns true if sector now resides in memory
379 //bool deFlushSector(v2s16 p2d);
381 void saveBlock(MapBlock *block);
382 // This will generate a sector with getSector if not found.
383 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
385 // Gets from master heightmap
386 void getSectorCorners(v2s16 p2d, s16 *corners);
388 // For debug printing
389 virtual void PrintInfo(std::ostream &out);
392 // Generator parameters
393 UnlimitedHeightmap *m_heightmap;
395 PointAttributeDatabase m_padb;
397 std::string m_savedir;
398 bool m_map_saving_enabled;
403 struct MapDrawControl
408 wanted_max_blocks(0),
411 blocks_would_have_drawn(0)
414 // Overrides limits by drawing everything
416 // Wanted drawing range
418 // Maximum number of blocks to draw
419 u32 wanted_max_blocks;
420 // Blocks in this range are drawn regardless of number of blocks drawn
421 float wanted_min_range;
422 // Number of blocks rendered is written here by the renderer
424 // Number of blocks that would have been drawn in wanted_range
425 u32 blocks_would_have_drawn;
433 This is the only map class that is able to render itself on screen.
436 class ClientMap : public Map, public scene::ISceneNode
441 MapDrawControl &control,
442 scene::ISceneNode* parent,
443 scene::ISceneManager* mgr,
451 return MAPTYPE_CLIENT;
460 Forcefully get a sector from somewhere
462 MapSector * emergeSector(v2s16 p);
464 void deSerializeSector(v2s16 p2d, std::istream &is);
470 virtual void OnRegisterSceneNode();
472 virtual void render()
474 video::IVideoDriver* driver = SceneManager->getVideoDriver();
475 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
476 renderMap(driver, SceneManager->getSceneNodeRenderPass());
479 virtual const core::aabbox3d<f32>& getBoundingBox() const
484 void renderMap(video::IVideoDriver* driver, s32 pass);
487 Methods for setting temporary modifications to nodes for
490 Returns true if something changed.
492 All blocks whose mesh could have been changed are inserted
495 bool setTempMod(v3s16 p, NodeMod mod,
496 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
497 bool clearTempMod(v3s16 p,
498 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
499 // Efficient implementation needs a cache of TempMods
500 //void clearTempMods();
502 // For debug printing
503 virtual void PrintInfo(std::ostream &out);
508 core::aabbox3d<f32> m_box;
510 // This is the master heightmap mesh
514 MapDrawControl &m_control;
519 class MapVoxelManipulator : public VoxelManipulator
522 MapVoxelManipulator(Map *map);
523 virtual ~MapVoxelManipulator();
527 VoxelManipulator::clear();
528 m_loaded_blocks.clear();
531 virtual void emerge(VoxelArea a, s32 caller_id=-1);
533 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
538 NOTE: This might be used or not
540 SUGG: How 'bout an another VoxelManipulator for storing the
541 information about which block is loaded?
543 core::map<v3s16, bool> m_loaded_blocks;
546 class ManualMapVoxelManipulator : public MapVoxelManipulator
549 ManualMapVoxelManipulator(Map *map);
550 virtual ~ManualMapVoxelManipulator();
552 virtual void emerge(VoxelArea a, s32 caller_id=-1);
554 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);