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"
45 #define MAPTYPE_BASE 0
46 #define MAPTYPE_SERVER 1
47 #define MAPTYPE_CLIENT 2
49 class Map : public NodeContainer, public Heightmappish
53 Map(std::ostream &dout);
56 virtual u16 nodeContainerId() const
58 return NODECONTAINER_ID_MAP;
61 virtual s32 mapType() const
71 void updateCamera(v3f pos, v3f dir)
73 JMutexAutoLock lock(m_camera_mutex);
74 m_camera_position = pos;
75 m_camera_direction = dir;
78 static core::aabbox3d<f32> getNodeBox(v3s16 p)
80 return core::aabbox3d<f32>(
81 (float)p.X * BS - 0.5*BS,
82 (float)p.Y * BS - 0.5*BS,
83 (float)p.Z * BS - 0.5*BS,
84 (float)p.X * BS + 0.5*BS,
85 (float)p.Y * BS + 0.5*BS,
86 (float)p.Z * BS + 0.5*BS
90 // On failure returns NULL
91 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
92 // On failure returns NULL
93 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
94 // On failure throws InvalidPositionException
95 MapSector * getSectorNoGenerate(v2s16 p2d);
96 // Gets an existing sector or creates an empty one
97 //MapSector * getSectorCreate(v2s16 p2d);
100 This is overloaded by ClientMap and ServerMap to allow
101 their differing fetch methods.
103 virtual MapSector * emergeSector(v2s16 p) = 0;
105 // Returns InvalidPositionException if not found
106 MapBlock * getBlockNoCreate(v3s16 p);
107 // Returns NULL if not found
108 MapBlock * getBlockNoCreateNoEx(v3s16 p);
109 // Gets an existing block or creates an empty one
110 //MapBlock * getBlockCreate(v3s16 p);
112 // Returns InvalidPositionException if not found
113 f32 getGroundHeight(v2s16 p, bool generate=false);
114 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
116 // Returns InvalidPositionException if not found
117 bool isNodeUnderground(v3s16 p);
119 // virtual from NodeContainer
120 bool isValidPosition(v3s16 p)
122 v3s16 blockpos = getNodeBlockPos(p);
125 blockref = getBlockNoCreate(blockpos);
127 catch(InvalidPositionException &e)
132 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
133 bool is_valid = blockref->isValidPosition(relpos);
137 // virtual from NodeContainer
138 // throws InvalidPositionException if not found
139 MapNode getNode(v3s16 p)
141 v3s16 blockpos = getNodeBlockPos(p);
142 MapBlock * blockref = getBlockNoCreate(blockpos);
143 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
145 return blockref->getNodeNoCheck(relpos);
148 // virtual from NodeContainer
149 // throws InvalidPositionException if not found
150 void setNode(v3s16 p, MapNode & n)
152 v3s16 blockpos = getNodeBlockPos(p);
153 MapBlock * blockref = getBlockNoCreate(blockpos);
154 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
155 blockref->setNodeNoCheck(relpos, n);
158 /*MapNode getNodeGenerate(v3s16 p)
160 v3s16 blockpos = getNodeBlockPos(p);
161 MapBlock * blockref = getBlock(blockpos);
162 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
164 return blockref->getNode(relpos);
167 /*void setNodeGenerate(v3s16 p, MapNode & n)
169 v3s16 blockpos = getNodeBlockPos(p);
170 MapBlock * blockref = getBlock(blockpos);
171 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
172 blockref->setNode(relpos, n);
175 void unspreadLight(enum LightBank bank,
176 core::map<v3s16, u8> & from_nodes,
177 core::map<v3s16, bool> & light_sources,
178 core::map<v3s16, MapBlock*> & modified_blocks);
180 void unLightNeighbors(enum LightBank bank,
181 v3s16 pos, u8 lightwas,
182 core::map<v3s16, bool> & light_sources,
183 core::map<v3s16, MapBlock*> & modified_blocks);
185 void spreadLight(enum LightBank bank,
186 core::map<v3s16, bool> & from_nodes,
187 core::map<v3s16, MapBlock*> & modified_blocks);
189 void lightNeighbors(enum LightBank bank,
191 core::map<v3s16, MapBlock*> & modified_blocks);
193 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
195 s16 propagateSunlight(v3s16 start,
196 core::map<v3s16, MapBlock*> & modified_blocks);
198 void updateLighting(enum LightBank bank,
199 core::map<v3s16, MapBlock*> & a_blocks,
200 core::map<v3s16, MapBlock*> & modified_blocks);
202 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
203 core::map<v3s16, MapBlock*> & modified_blocks);
206 These handle lighting but not faces.
208 void addNodeAndUpdate(v3s16 p, MapNode n,
209 core::map<v3s16, MapBlock*> &modified_blocks);
210 void removeNodeAndUpdate(v3s16 p,
211 core::map<v3s16, MapBlock*> &modified_blocks);
214 void expireMeshes(bool only_daynight_diffed);
217 Update the faces of the given block and blocks on the
220 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
222 // Update meshes that touch the node
223 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
227 Takes the blocks at the edges into account
229 bool dayNightDiffed(v3s16 blockpos);
231 //core::aabbox3d<s16> getDisplayedBlockArea();
233 //bool updateChangedVisibleArea();
235 virtual void save(bool only_changed){assert(0);};
240 void timerUpdate(float dtime);
242 // Takes cache into account
243 // sector mutex should be locked when calling
244 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
246 // Returns count of deleted sectors
247 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
248 core::list<v3s16> *deleted_blocks=NULL);
250 // For debug printing
251 virtual void PrintInfo(std::ostream &out);
253 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
261 std::ostream &m_dout;
263 core::map<v2s16, MapSector*> m_sectors;
264 JMutex m_sector_mutex;
266 v3f m_camera_position;
267 v3f m_camera_direction;
268 JMutex m_camera_mutex;
270 // Be sure to set this to NULL when the cached sector is deleted
271 MapSector *m_sector_cache;
272 v2s16 m_sector_cache_p;
274 WrapperHeightmap m_hwrapper;
276 // Queued transforming water nodes
277 UniqueQueue<v3s16> m_transforming_liquid;
280 // Master heightmap parameters
286 randmax = "constant 70.0";
287 randfactor = "constant 0.6";
288 base = "linear 0 80 0";
292 std::string randfactor;
302 ravines_amount = 1.0;
303 //max_objects_in_block = 30;
306 float ravines_amount;
307 //u16 max_objects_in_block;
313 This is the only map class that is able to generate map.
316 class ServerMap : public Map
320 savedir: directory to which map data should be saved
322 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
327 return MAPTYPE_SERVER;
334 // Returns the position of the chunk where the sector is in
335 v2s16 sector_to_chunk(v2s16 sectorpos)
337 sectorpos.X += m_chunksize / 2;
338 sectorpos.Y += m_chunksize / 2;
339 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
343 // Returns the position of the (0,0) sector of the chunk
344 v2s16 chunk_to_sector(v2s16 chunkpos)
347 chunkpos.X * m_chunksize,
348 chunkpos.Y * m_chunksize
350 sectorpos.X -= m_chunksize / 2;
351 sectorpos.Y -= m_chunksize / 2;
358 MapChunk *getChunk(v2s16 chunkpos)
360 core::map<v2s16, MapChunk*>::Node *n;
361 n = m_chunks.find(chunkpos);
364 return n->getValue();
370 All chunks touching this one can be altered also.
372 Doesn't update lighting.
374 MapChunk* generateChunkRaw(v2s16 chunkpos);
377 Generate a chunk and its neighbors so that it won't be touched
380 Doesn't update lighting.
382 MapChunk* generateChunk(v2s16 chunkpos);
387 This is mainly called by generateChunkRaw.
389 //ServerMapSector * generateSector(v2s16 p);
392 Get a sector from somewhere.
394 - Check disk (loads blocks also)
397 ServerMapSector * createSector(v2s16 p);
400 Get a sector from somewhere.
402 - Check disk (loads blocks also)
405 MapSector * emergeSector(v2s16 p);
407 MapBlock * generateBlock(
409 MapBlock *original_dummy,
410 ServerMapSector *sector,
411 core::map<v3s16, MapBlock*> &changed_blocks,
412 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
416 Get a block from somewhere.
420 MapBlock * createBlock(v3s16 p);
422 MapBlock * emergeBlock(
425 core::map<v3s16, MapBlock*> &changed_blocks,
426 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
431 Forcefully get a block from somewhere.
434 - InvalidPositionException: possible if only_from_disk==true
437 - All already existing blocks that were modified are added.
438 - If found on disk, nothing will be added.
439 - If generated, the new block will not be included.
441 lighting_invalidated_blocks:
442 - All blocks that have heavy-to-calculate lighting changes
444 - updateLighting() should be called for these.
446 - A block that is in changed_blocks may not be in
447 lighting_invalidated_blocks.
449 MapBlock * emergeBlock(
452 core::map<v3s16, MapBlock*> &changed_blocks,
453 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
458 Misc. helper functions for fiddling with directory and file
461 void createDir(std::string path);
462 void createSaveDir();
463 // returns something like "xxxxxxxx"
464 std::string getSectorSubDir(v2s16 pos);
465 // returns something like "map/sectors/xxxxxxxx"
466 std::string getSectorDir(v2s16 pos);
467 std::string createSectorDir(v2s16 pos);
468 // dirname: final directory name
469 v2s16 getSectorPos(std::string dirname);
470 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
472 void save(bool only_changed);
475 void saveMasterHeightmap();
476 void loadMasterHeightmap();
478 // The sector mutex should be locked when calling most of these
480 // This only saves sector-specific data such as the heightmap
482 void saveSectorMeta(ServerMapSector *sector);
483 MapSector* loadSectorMeta(std::string dirname);
485 // Full load of a sector including all blocks.
486 // returns true on success, false on failure.
487 bool loadSectorFull(v2s16 p2d);
488 // If sector is not found in memory, try to load it from disk.
489 // Returns true if sector now resides in memory
490 //bool deFlushSector(v2s16 p2d);
492 void saveBlock(MapBlock *block);
493 // This will generate a sector with getSector if not found.
494 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
496 // Gets from master heightmap
497 void getSectorCorners(v2s16 p2d, s16 *corners);
499 // For debug printing
500 virtual void PrintInfo(std::ostream &out);
503 // Generator parameters
504 UnlimitedHeightmap *m_heightmap;
506 PointAttributeDatabase m_padb;
508 std::string m_savedir;
509 bool m_map_saving_enabled;
511 // Chunk size in MapSectors
514 core::map<v2s16, MapChunk*> m_chunks;
523 struct MapDrawControl
528 wanted_max_blocks(0),
531 blocks_would_have_drawn(0)
534 // Overrides limits by drawing everything
536 // Wanted drawing range
538 // Maximum number of blocks to draw
539 u32 wanted_max_blocks;
540 // Blocks in this range are drawn regardless of number of blocks drawn
541 float wanted_min_range;
542 // Number of blocks rendered is written here by the renderer
544 // Number of blocks that would have been drawn in wanted_range
545 u32 blocks_would_have_drawn;
553 This is the only map class that is able to render itself on screen.
556 class ClientMap : public Map, public scene::ISceneNode
561 MapDrawControl &control,
562 scene::ISceneNode* parent,
563 scene::ISceneManager* mgr,
571 return MAPTYPE_CLIENT;
580 Forcefully get a sector from somewhere
582 MapSector * emergeSector(v2s16 p);
584 void deSerializeSector(v2s16 p2d, std::istream &is);
590 virtual void OnRegisterSceneNode();
592 virtual void render()
594 video::IVideoDriver* driver = SceneManager->getVideoDriver();
595 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
596 renderMap(driver, SceneManager->getSceneNodeRenderPass());
599 virtual const core::aabbox3d<f32>& getBoundingBox() const
604 void renderMap(video::IVideoDriver* driver, s32 pass);
607 Methods for setting temporary modifications to nodes for
610 Returns true if something changed.
612 All blocks whose mesh could have been changed are inserted
615 bool setTempMod(v3s16 p, NodeMod mod,
616 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
617 bool clearTempMod(v3s16 p,
618 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
619 // Efficient implementation needs a cache of TempMods
620 //void clearTempMods();
622 // For debug printing
623 virtual void PrintInfo(std::ostream &out);
628 core::aabbox3d<f32> m_box;
630 // This is the master heightmap mesh
634 MapDrawControl &m_control;
639 class MapVoxelManipulator : public VoxelManipulator
642 MapVoxelManipulator(Map *map);
643 virtual ~MapVoxelManipulator();
647 VoxelManipulator::clear();
648 m_loaded_blocks.clear();
651 virtual void emerge(VoxelArea a, s32 caller_id=-1);
653 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
659 value = block existed when loaded
661 core::map<v3s16, bool> m_loaded_blocks;
664 class ManualMapVoxelManipulator : public MapVoxelManipulator
667 ManualMapVoxelManipulator(Map *map);
668 virtual ~ManualMapVoxelManipulator();
670 virtual void emerge(VoxelArea a, s32 caller_id=-1);
672 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
674 // This is much faster with big chunks of generated data
675 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);