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){ return NULL; }
104 virtual MapSector * emergeSector(v2s16 p,
105 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
107 // Returns InvalidPositionException if not found
108 MapBlock * getBlockNoCreate(v3s16 p);
109 // Returns NULL if not found
110 MapBlock * getBlockNoCreateNoEx(v3s16 p);
111 // Gets an existing block or creates an empty one
112 //MapBlock * getBlockCreate(v3s16 p);
114 // Returns InvalidPositionException if not found
115 f32 getGroundHeight(v2s16 p, bool generate=false);
116 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
118 // Returns InvalidPositionException if not found
119 bool isNodeUnderground(v3s16 p);
121 // virtual from NodeContainer
122 bool isValidPosition(v3s16 p)
124 v3s16 blockpos = getNodeBlockPos(p);
127 blockref = getBlockNoCreate(blockpos);
129 catch(InvalidPositionException &e)
134 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
135 bool is_valid = blockref->isValidPosition(relpos);
139 // virtual from NodeContainer
140 // throws InvalidPositionException if not found
141 MapNode getNode(v3s16 p)
143 v3s16 blockpos = getNodeBlockPos(p);
144 MapBlock * blockref = getBlockNoCreate(blockpos);
145 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
147 return blockref->getNodeNoCheck(relpos);
150 // virtual from NodeContainer
151 // throws InvalidPositionException if not found
152 void setNode(v3s16 p, MapNode & n)
154 v3s16 blockpos = getNodeBlockPos(p);
155 MapBlock * blockref = getBlockNoCreate(blockpos);
156 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
157 blockref->setNodeNoCheck(relpos, n);
160 /*MapNode getNodeGenerate(v3s16 p)
162 v3s16 blockpos = getNodeBlockPos(p);
163 MapBlock * blockref = getBlock(blockpos);
164 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
166 return blockref->getNode(relpos);
169 /*void setNodeGenerate(v3s16 p, MapNode & n)
171 v3s16 blockpos = getNodeBlockPos(p);
172 MapBlock * blockref = getBlock(blockpos);
173 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
174 blockref->setNode(relpos, n);
177 void unspreadLight(enum LightBank bank,
178 core::map<v3s16, u8> & from_nodes,
179 core::map<v3s16, bool> & light_sources,
180 core::map<v3s16, MapBlock*> & modified_blocks);
182 void unLightNeighbors(enum LightBank bank,
183 v3s16 pos, u8 lightwas,
184 core::map<v3s16, bool> & light_sources,
185 core::map<v3s16, MapBlock*> & modified_blocks);
187 void spreadLight(enum LightBank bank,
188 core::map<v3s16, bool> & from_nodes,
189 core::map<v3s16, MapBlock*> & modified_blocks);
191 void lightNeighbors(enum LightBank bank,
193 core::map<v3s16, MapBlock*> & modified_blocks);
195 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
197 s16 propagateSunlight(v3s16 start,
198 core::map<v3s16, MapBlock*> & modified_blocks);
200 void updateLighting(enum LightBank bank,
201 core::map<v3s16, MapBlock*> & a_blocks,
202 core::map<v3s16, MapBlock*> & modified_blocks);
204 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
205 core::map<v3s16, MapBlock*> & modified_blocks);
208 These handle lighting but not faces.
210 void addNodeAndUpdate(v3s16 p, MapNode n,
211 core::map<v3s16, MapBlock*> &modified_blocks);
212 void removeNodeAndUpdate(v3s16 p,
213 core::map<v3s16, MapBlock*> &modified_blocks);
216 void expireMeshes(bool only_daynight_diffed);
219 Update the faces of the given block and blocks on the
222 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
224 // Update meshes that touch the node
225 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
229 Takes the blocks at the edges into account
231 bool dayNightDiffed(v3s16 blockpos);
233 //core::aabbox3d<s16> getDisplayedBlockArea();
235 //bool updateChangedVisibleArea();
237 virtual void save(bool only_changed){assert(0);};
242 void timerUpdate(float dtime);
244 // Takes cache into account
245 // sector mutex should be locked when calling
246 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
248 // Returns count of deleted sectors
249 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
250 core::list<v3s16> *deleted_blocks=NULL);
252 // For debug printing
253 virtual void PrintInfo(std::ostream &out);
255 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
263 std::ostream &m_dout;
265 core::map<v2s16, MapSector*> m_sectors;
266 JMutex m_sector_mutex;
268 v3f m_camera_position;
269 v3f m_camera_direction;
270 JMutex m_camera_mutex;
272 // Be sure to set this to NULL when the cached sector is deleted
273 MapSector *m_sector_cache;
274 v2s16 m_sector_cache_p;
276 WrapperHeightmap m_hwrapper;
278 // Queued transforming water nodes
279 UniqueQueue<v3s16> m_transforming_liquid;
282 // Master heightmap parameters
288 randmax = "constant 70.0";
289 randfactor = "constant 0.6";
290 base = "linear 0 80 0";
294 std::string randfactor;
304 ravines_amount = 1.0;
305 //max_objects_in_block = 30;
308 float ravines_amount;
309 //u16 max_objects_in_block;
315 This is the only map class that is able to generate map.
318 class ServerMap : public Map
322 savedir: directory to which map data should be saved
324 ServerMap(std::string savedir, HMParams hmp, MapParams mp);
329 return MAPTYPE_SERVER;
336 // Returns the position of the chunk where the sector is in
337 v2s16 sector_to_chunk(v2s16 sectorpos)
339 sectorpos.X += m_chunksize / 2;
340 sectorpos.Y += m_chunksize / 2;
341 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
345 // Returns the position of the (0,0) sector of the chunk
346 v2s16 chunk_to_sector(v2s16 chunkpos)
349 chunkpos.X * m_chunksize,
350 chunkpos.Y * m_chunksize
352 sectorpos.X -= m_chunksize / 2;
353 sectorpos.Y -= m_chunksize / 2;
360 MapChunk *getChunk(v2s16 chunkpos)
362 core::map<v2s16, MapChunk*>::Node *n;
363 n = m_chunks.find(chunkpos);
366 return n->getValue();
370 True if the chunk and its neighbors are fully generated.
371 It means the chunk will not be touched in the future by the
372 generator. If false, generateChunk will make it true.
374 bool chunkNonVolatile(v2s16 chunkpos)
376 /*for(s16 x=-1; x<=1; x++)
377 for(s16 y=-1; y<=1; y++)*/
381 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
382 MapChunk *chunk = getChunk(chunkpos);
385 if(chunk->getGenLevel() != GENERATED_FULLY)
394 All chunks touching this one can be altered also.
396 MapChunk* generateChunkRaw(v2s16 chunkpos,
397 core::map<v3s16, MapBlock*> &changed_blocks);
400 Generate a chunk and its neighbors so that it won't be touched
403 MapChunk* generateChunk(v2s16 chunkpos,
404 core::map<v3s16, MapBlock*> &changed_blocks);
409 This is mainly called by generateChunkRaw.
411 //ServerMapSector * generateSector(v2s16 p);
414 Get a sector from somewhere.
416 - Check disk (loads blocks also)
419 ServerMapSector * createSector(v2s16 p);
422 Get a sector from somewhere.
424 - Check disk (loads blocks also)
427 MapSector * emergeSector(v2s16 p,
428 core::map<v3s16, MapBlock*> &changed_blocks);
430 MapSector * emergeSector(v2s16 p)
432 core::map<v3s16, MapBlock*> changed_blocks;
433 return emergeSector(p, changed_blocks);
436 MapBlock * generateBlock(
438 MapBlock *original_dummy,
439 ServerMapSector *sector,
440 core::map<v3s16, MapBlock*> &changed_blocks,
441 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
445 Get a block from somewhere.
449 MapBlock * createBlock(v3s16 p);
452 only_from_disk, changed_blocks and lighting_invalidated_blocks
453 are not properly used by the new map generator.
455 MapBlock * emergeBlock(
458 core::map<v3s16, MapBlock*> &changed_blocks,
459 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
464 Forcefully get a block from somewhere.
467 - InvalidPositionException: possible if only_from_disk==true
470 - All already existing blocks that were modified are added.
471 - If found on disk, nothing will be added.
472 - If generated, the new block will not be included.
474 lighting_invalidated_blocks:
475 - All blocks that have heavy-to-calculate lighting changes
477 - updateLighting() should be called for these.
479 - A block that is in changed_blocks may not be in
480 lighting_invalidated_blocks.
482 MapBlock * emergeBlock(
485 core::map<v3s16, MapBlock*> &changed_blocks,
486 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
491 Misc. helper functions for fiddling with directory and file
494 void createDir(std::string path);
495 void createSaveDir();
496 // returns something like "xxxxxxxx"
497 std::string getSectorSubDir(v2s16 pos);
498 // returns something like "map/sectors/xxxxxxxx"
499 std::string getSectorDir(v2s16 pos);
500 std::string createSectorDir(v2s16 pos);
501 // dirname: final directory name
502 v2s16 getSectorPos(std::string dirname);
503 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
505 void save(bool only_changed);
508 void saveMasterHeightmap();
509 void loadMasterHeightmap();
511 // The sector mutex should be locked when calling most of these
513 // This only saves sector-specific data such as the heightmap
515 void saveSectorMeta(ServerMapSector *sector);
516 MapSector* loadSectorMeta(std::string dirname);
518 // Full load of a sector including all blocks.
519 // returns true on success, false on failure.
520 bool loadSectorFull(v2s16 p2d);
521 // If sector is not found in memory, try to load it from disk.
522 // Returns true if sector now resides in memory
523 //bool deFlushSector(v2s16 p2d);
525 void saveBlock(MapBlock *block);
526 // This will generate a sector with getSector if not found.
527 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
529 // Gets from master heightmap
530 void getSectorCorners(v2s16 p2d, s16 *corners);
532 // For debug printing
533 virtual void PrintInfo(std::ostream &out);
536 // Generator parameters
537 UnlimitedHeightmap *m_heightmap;
539 PointAttributeDatabase m_padb;
541 std::string m_savedir;
542 bool m_map_saving_enabled;
544 // Chunk size in MapSectors
547 core::map<v2s16, MapChunk*> m_chunks;
556 struct MapDrawControl
561 wanted_max_blocks(0),
564 blocks_would_have_drawn(0)
567 // Overrides limits by drawing everything
569 // Wanted drawing range
571 // Maximum number of blocks to draw
572 u32 wanted_max_blocks;
573 // Blocks in this range are drawn regardless of number of blocks drawn
574 float wanted_min_range;
575 // Number of blocks rendered is written here by the renderer
577 // Number of blocks that would have been drawn in wanted_range
578 u32 blocks_would_have_drawn;
586 This is the only map class that is able to render itself on screen.
589 class ClientMap : public Map, public scene::ISceneNode
594 MapDrawControl &control,
595 scene::ISceneNode* parent,
596 scene::ISceneManager* mgr,
604 return MAPTYPE_CLIENT;
613 Forcefully get a sector from somewhere
615 MapSector * emergeSector(v2s16 p);
617 void deSerializeSector(v2s16 p2d, std::istream &is);
623 virtual void OnRegisterSceneNode();
625 virtual void render()
627 video::IVideoDriver* driver = SceneManager->getVideoDriver();
628 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
629 renderMap(driver, SceneManager->getSceneNodeRenderPass());
632 virtual const core::aabbox3d<f32>& getBoundingBox() const
637 void renderMap(video::IVideoDriver* driver, s32 pass);
640 Methods for setting temporary modifications to nodes for
643 Returns true if something changed.
645 All blocks whose mesh could have been changed are inserted
648 bool setTempMod(v3s16 p, NodeMod mod,
649 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
650 bool clearTempMod(v3s16 p,
651 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
652 // Efficient implementation needs a cache of TempMods
653 //void clearTempMods();
655 // For debug printing
656 virtual void PrintInfo(std::ostream &out);
661 core::aabbox3d<f32> m_box;
663 // This is the master heightmap mesh
667 MapDrawControl &m_control;
672 class MapVoxelManipulator : public VoxelManipulator
675 MapVoxelManipulator(Map *map);
676 virtual ~MapVoxelManipulator();
680 VoxelManipulator::clear();
681 m_loaded_blocks.clear();
684 virtual void emerge(VoxelArea a, s32 caller_id=-1);
686 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
692 value = block existed when loaded
694 core::map<v3s16, bool> m_loaded_blocks;
697 class ManualMapVoxelManipulator : public MapVoxelManipulator
700 ManualMapVoxelManipulator(Map *map);
701 virtual ~ManualMapVoxelManipulator();
703 virtual void emerge(VoxelArea a, s32 caller_id=-1);
705 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
707 // This is much faster with big chunks of generated data
708 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);