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
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;
285 This is the only map class that is able to generate map.
288 class ServerMap : public Map
292 savedir: directory to which map data should be saved
294 ServerMap(std::string savedir);
299 return MAPTYPE_SERVER;
306 // Returns the position of the chunk where the sector is in
307 v2s16 sector_to_chunk(v2s16 sectorpos)
309 sectorpos.X += m_chunksize / 2;
310 sectorpos.Y += m_chunksize / 2;
311 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
315 // Returns the position of the (0,0) sector of the chunk
316 v2s16 chunk_to_sector(v2s16 chunkpos)
319 chunkpos.X * m_chunksize,
320 chunkpos.Y * m_chunksize
322 sectorpos.X -= m_chunksize / 2;
323 sectorpos.Y -= m_chunksize / 2;
330 MapChunk *getChunk(v2s16 chunkpos)
332 core::map<v2s16, MapChunk*>::Node *n;
333 n = m_chunks.find(chunkpos);
336 return n->getValue();
340 True if the chunk and its neighbors are fully generated.
341 It means the chunk will not be touched in the future by the
342 generator. If false, generateChunk will make it true.
344 bool chunkNonVolatile(v2s16 chunkpos)
346 /*for(s16 x=-1; x<=1; x++)
347 for(s16 y=-1; y<=1; y++)*/
351 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
352 MapChunk *chunk = getChunk(chunkpos);
355 if(chunk->getGenLevel() != GENERATED_FULLY)
364 All chunks touching this one can be altered also.
366 MapChunk* generateChunkRaw(v2s16 chunkpos,
367 core::map<v3s16, MapBlock*> &changed_blocks);
370 Generate a chunk and its neighbors so that it won't be touched
373 MapChunk* generateChunk(v2s16 chunkpos,
374 core::map<v3s16, MapBlock*> &changed_blocks);
379 This is mainly called by generateChunkRaw.
381 //ServerMapSector * generateSector(v2s16 p);
384 Get a sector from somewhere.
386 - Check disk (loads blocks also)
389 ServerMapSector * createSector(v2s16 p);
392 Get a sector from somewhere.
394 - Check disk (loads blocks also)
397 MapSector * emergeSector(v2s16 p,
398 core::map<v3s16, MapBlock*> &changed_blocks);
400 MapSector * emergeSector(v2s16 p)
402 core::map<v3s16, MapBlock*> changed_blocks;
403 return emergeSector(p, changed_blocks);
406 MapBlock * generateBlock(
408 MapBlock *original_dummy,
409 ServerMapSector *sector,
410 core::map<v3s16, MapBlock*> &changed_blocks,
411 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
415 Get a block from somewhere.
419 MapBlock * createBlock(v3s16 p);
422 only_from_disk, changed_blocks and lighting_invalidated_blocks
423 are not properly used by the new map generator.
425 MapBlock * emergeBlock(
428 core::map<v3s16, MapBlock*> &changed_blocks,
429 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
434 Forcefully get a block from somewhere.
437 - InvalidPositionException: possible if only_from_disk==true
440 - All already existing blocks that were modified are added.
441 - If found on disk, nothing will be added.
442 - If generated, the new block will not be included.
444 lighting_invalidated_blocks:
445 - All blocks that have heavy-to-calculate lighting changes
447 - updateLighting() should be called for these.
449 - A block that is in changed_blocks may not be in
450 lighting_invalidated_blocks.
452 MapBlock * emergeBlock(
455 core::map<v3s16, MapBlock*> &changed_blocks,
456 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
461 Misc. helper functions for fiddling with directory and file
464 void createDir(std::string path);
465 void createSaveDir();
466 // returns something like "xxxxxxxx"
467 std::string getSectorSubDir(v2s16 pos);
468 // returns something like "map/sectors/xxxxxxxx"
469 std::string getSectorDir(v2s16 pos);
470 std::string createSectorDir(v2s16 pos);
471 // dirname: final directory name
472 v2s16 getSectorPos(std::string dirname);
473 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
475 void save(bool only_changed);
483 void saveChunkMeta();
484 void loadChunkMeta();
487 void saveMasterHeightmap();
488 void loadMasterHeightmap();
490 // The sector mutex should be locked when calling most of these
492 // This only saves sector-specific data such as the heightmap
494 // DEPRECATED? Sectors have no metadata anymore.
495 void saveSectorMeta(ServerMapSector *sector);
496 MapSector* loadSectorMeta(std::string dirname);
498 // Full load of a sector including all blocks.
499 // returns true on success, false on failure.
500 bool loadSectorFull(v2s16 p2d);
501 // If sector is not found in memory, try to load it from disk.
502 // Returns true if sector now resides in memory
503 //bool deFlushSector(v2s16 p2d);
505 void saveBlock(MapBlock *block);
506 // This will generate a sector with getSector if not found.
507 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
509 // Gets from master heightmap
511 void getSectorCorners(v2s16 p2d, s16 *corners);
513 // For debug printing
514 virtual void PrintInfo(std::ostream &out);
517 // Seed used for all kinds of randomness
520 std::string m_savedir;
521 bool m_map_saving_enabled;
523 // Chunk size in MapSectors
526 core::map<v2s16, MapChunk*> m_chunks;
535 struct MapDrawControl
540 wanted_max_blocks(0),
543 blocks_would_have_drawn(0)
546 // Overrides limits by drawing everything
548 // Wanted drawing range
550 // Maximum number of blocks to draw
551 u32 wanted_max_blocks;
552 // Blocks in this range are drawn regardless of number of blocks drawn
553 float wanted_min_range;
554 // Number of blocks rendered is written here by the renderer
556 // Number of blocks that would have been drawn in wanted_range
557 u32 blocks_would_have_drawn;
565 This is the only map class that is able to render itself on screen.
568 class ClientMap : public Map, public scene::ISceneNode
573 MapDrawControl &control,
574 scene::ISceneNode* parent,
575 scene::ISceneManager* mgr,
583 return MAPTYPE_CLIENT;
592 Forcefully get a sector from somewhere
594 MapSector * emergeSector(v2s16 p);
596 void deSerializeSector(v2s16 p2d, std::istream &is);
602 virtual void OnRegisterSceneNode();
604 virtual void render()
606 video::IVideoDriver* driver = SceneManager->getVideoDriver();
607 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
608 renderMap(driver, SceneManager->getSceneNodeRenderPass());
611 virtual const core::aabbox3d<f32>& getBoundingBox() const
616 void renderMap(video::IVideoDriver* driver, s32 pass);
619 Methods for setting temporary modifications to nodes for
622 Returns true if something changed.
624 All blocks whose mesh could have been changed are inserted
627 bool setTempMod(v3s16 p, NodeMod mod,
628 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
629 bool clearTempMod(v3s16 p,
630 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
631 // Efficient implementation needs a cache of TempMods
632 //void clearTempMods();
634 // For debug printing
635 virtual void PrintInfo(std::ostream &out);
640 core::aabbox3d<f32> m_box;
642 // This is the master heightmap mesh
643 //scene::SMesh *mesh;
646 MapDrawControl &m_control;
651 class MapVoxelManipulator : public VoxelManipulator
654 MapVoxelManipulator(Map *map);
655 virtual ~MapVoxelManipulator();
659 VoxelManipulator::clear();
660 m_loaded_blocks.clear();
663 virtual void emerge(VoxelArea a, s32 caller_id=-1);
665 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
671 value = block existed when loaded
673 core::map<v3s16, bool> m_loaded_blocks;
676 class ManualMapVoxelManipulator : public MapVoxelManipulator
679 ManualMapVoxelManipulator(Map *map);
680 virtual ~ManualMapVoxelManipulator();
682 virtual void emerge(VoxelArea a, s32 caller_id=-1);
684 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
686 // This is much faster with big chunks of generated data
687 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);