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.
29 #define sleep_s(x) Sleep((x*1000))
32 #define sleep_s(x) sleep(x)
35 #include "common_irrlicht.h"
36 //#include "heightmap.h"
39 #include "mapsector.h"
40 #include "constants.h"
44 #define MAPTYPE_BASE 0
45 #define MAPTYPE_SERVER 1
46 #define MAPTYPE_CLIENT 2
48 class Map : public NodeContainer
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 // On failure returns NULL
90 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
91 // On failure returns NULL
92 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
93 // On failure throws InvalidPositionException
94 MapSector * getSectorNoGenerate(v2s16 p2d);
95 // Gets an existing sector or creates an empty one
96 //MapSector * getSectorCreate(v2s16 p2d);
99 This is overloaded by ClientMap and ServerMap to allow
100 their differing fetch methods.
102 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
103 virtual MapSector * emergeSector(v2s16 p,
104 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
106 // Returns InvalidPositionException if not found
107 MapBlock * getBlockNoCreate(v3s16 p);
108 // Returns NULL if not found
109 MapBlock * getBlockNoCreateNoEx(v3s16 p);
110 // Gets an existing block or creates an empty one
111 //MapBlock * getBlockCreate(v3s16 p);
113 // Returns InvalidPositionException if not found
114 f32 getGroundHeight(v2s16 p, bool generate=false);
115 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
117 // Returns InvalidPositionException if not found
118 bool isNodeUnderground(v3s16 p);
120 // virtual from NodeContainer
121 bool isValidPosition(v3s16 p)
123 v3s16 blockpos = getNodeBlockPos(p);
126 blockref = getBlockNoCreate(blockpos);
128 catch(InvalidPositionException &e)
133 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
134 bool is_valid = blockref->isValidPosition(relpos);
138 // virtual from NodeContainer
139 // throws InvalidPositionException if not found
140 MapNode getNode(v3s16 p)
142 v3s16 blockpos = getNodeBlockPos(p);
143 MapBlock * blockref = getBlockNoCreate(blockpos);
144 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
146 return blockref->getNodeNoCheck(relpos);
149 // virtual from NodeContainer
150 // throws InvalidPositionException if not found
151 void setNode(v3s16 p, MapNode & n)
153 v3s16 blockpos = getNodeBlockPos(p);
154 MapBlock * blockref = getBlockNoCreate(blockpos);
155 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
156 blockref->setNodeNoCheck(relpos, n);
159 /*MapNode getNodeGenerate(v3s16 p)
161 v3s16 blockpos = getNodeBlockPos(p);
162 MapBlock * blockref = getBlock(blockpos);
163 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
165 return blockref->getNode(relpos);
168 /*void setNodeGenerate(v3s16 p, MapNode & n)
170 v3s16 blockpos = getNodeBlockPos(p);
171 MapBlock * blockref = getBlock(blockpos);
172 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
173 blockref->setNode(relpos, n);
176 void unspreadLight(enum LightBank bank,
177 core::map<v3s16, u8> & from_nodes,
178 core::map<v3s16, bool> & light_sources,
179 core::map<v3s16, MapBlock*> & modified_blocks);
181 void unLightNeighbors(enum LightBank bank,
182 v3s16 pos, u8 lightwas,
183 core::map<v3s16, bool> & light_sources,
184 core::map<v3s16, MapBlock*> & modified_blocks);
186 void spreadLight(enum LightBank bank,
187 core::map<v3s16, bool> & from_nodes,
188 core::map<v3s16, MapBlock*> & modified_blocks);
190 void lightNeighbors(enum LightBank bank,
192 core::map<v3s16, MapBlock*> & modified_blocks);
194 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
196 s16 propagateSunlight(v3s16 start,
197 core::map<v3s16, MapBlock*> & modified_blocks);
199 void updateLighting(enum LightBank bank,
200 core::map<v3s16, MapBlock*> & a_blocks,
201 core::map<v3s16, MapBlock*> & modified_blocks);
203 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
204 core::map<v3s16, MapBlock*> & modified_blocks);
207 These handle lighting but not faces.
209 void addNodeAndUpdate(v3s16 p, MapNode n,
210 core::map<v3s16, MapBlock*> &modified_blocks);
211 void removeNodeAndUpdate(v3s16 p,
212 core::map<v3s16, MapBlock*> &modified_blocks);
215 void expireMeshes(bool only_daynight_diffed);
218 Update the faces of the given block and blocks on the
221 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
223 // Update meshes that touch the node
224 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
228 Takes the blocks at the edges into account
230 bool dayNightDiffed(v3s16 blockpos);
232 //core::aabbox3d<s16> getDisplayedBlockArea();
234 //bool updateChangedVisibleArea();
236 virtual void save(bool only_changed){assert(0);};
241 void timerUpdate(float dtime);
243 // Takes cache into account
244 // sector mutex should be locked when calling
245 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
247 // Returns count of deleted sectors
248 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
249 core::list<v3s16> *deleted_blocks=NULL);
251 // For debug printing
252 virtual void PrintInfo(std::ostream &out);
254 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
262 std::ostream &m_dout;
264 core::map<v2s16, MapSector*> m_sectors;
265 JMutex m_sector_mutex;
267 v3f m_camera_position;
268 v3f m_camera_direction;
269 JMutex m_camera_mutex;
271 // Be sure to set this to NULL when the cached sector is deleted
272 MapSector *m_sector_cache;
273 v2s16 m_sector_cache_p;
275 //WrapperHeightmap m_hwrapper;
277 // Queued transforming water nodes
278 UniqueQueue<v3s16> m_transforming_liquid;
284 This is the only map class that is able to generate map.
287 class ServerMap : public Map
291 savedir: directory to which map data should be saved
293 ServerMap(std::string savedir);
298 return MAPTYPE_SERVER;
305 // Returns the position of the chunk where the sector is in
306 v2s16 sector_to_chunk(v2s16 sectorpos)
308 sectorpos.X += m_chunksize / 2;
309 sectorpos.Y += m_chunksize / 2;
310 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
314 // Returns the position of the (0,0) sector of the chunk
315 v2s16 chunk_to_sector(v2s16 chunkpos)
318 chunkpos.X * m_chunksize,
319 chunkpos.Y * m_chunksize
321 sectorpos.X -= m_chunksize / 2;
322 sectorpos.Y -= m_chunksize / 2;
329 MapChunk *getChunk(v2s16 chunkpos)
331 core::map<v2s16, MapChunk*>::Node *n;
332 n = m_chunks.find(chunkpos);
335 return n->getValue();
339 True if the chunk and its neighbors are fully generated.
340 It means the chunk will not be touched in the future by the
341 generator. If false, generateChunk will make it true.
343 bool chunkNonVolatile(v2s16 chunkpos)
345 /*for(s16 x=-1; x<=1; x++)
346 for(s16 y=-1; y<=1; y++)*/
350 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
351 MapChunk *chunk = getChunk(chunkpos);
354 if(chunk->getGenLevel() != GENERATED_FULLY)
363 All chunks touching this one can be altered also.
365 MapChunk* generateChunkRaw(v2s16 chunkpos,
366 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);
478 // Saves map seed and possibly other stuff
482 void saveChunkMeta();
483 void loadChunkMeta();
485 // The sector mutex should be locked when calling most of these
487 // This only saves sector-specific data such as the heightmap
489 // DEPRECATED? Sectors have no metadata anymore.
490 void saveSectorMeta(ServerMapSector *sector);
491 MapSector* loadSectorMeta(std::string dirname);
493 // Full load of a sector including all blocks.
494 // returns true on success, false on failure.
495 bool loadSectorFull(v2s16 p2d);
496 // If sector is not found in memory, try to load it from disk.
497 // Returns true if sector now resides in memory
498 //bool deFlushSector(v2s16 p2d);
500 void saveBlock(MapBlock *block);
501 // This will generate a sector with getSector if not found.
502 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
504 // Gets from master heightmap
506 void getSectorCorners(v2s16 p2d, s16 *corners);
508 // For debug printing
509 virtual void PrintInfo(std::ostream &out);
511 bool isSavingEnabled(){ return m_map_saving_enabled; }
514 // Seed used for all kinds of randomness
517 std::string m_savedir;
518 bool m_map_saving_enabled;
520 // Chunk size in MapSectors
523 core::map<v2s16, MapChunk*> m_chunks;
532 struct MapDrawControl
537 wanted_max_blocks(0),
540 blocks_would_have_drawn(0)
543 // Overrides limits by drawing everything
545 // Wanted drawing range
547 // Maximum number of blocks to draw
548 u32 wanted_max_blocks;
549 // Blocks in this range are drawn regardless of number of blocks drawn
550 float wanted_min_range;
551 // Number of blocks rendered is written here by the renderer
553 // Number of blocks that would have been drawn in wanted_range
554 u32 blocks_would_have_drawn;
562 This is the only map class that is able to render itself on screen.
565 class ClientMap : public Map, public scene::ISceneNode
570 MapDrawControl &control,
571 scene::ISceneNode* parent,
572 scene::ISceneManager* mgr,
580 return MAPTYPE_CLIENT;
589 Forcefully get a sector from somewhere
591 MapSector * emergeSector(v2s16 p);
593 void deSerializeSector(v2s16 p2d, std::istream &is);
599 virtual void OnRegisterSceneNode();
601 virtual void render()
603 video::IVideoDriver* driver = SceneManager->getVideoDriver();
604 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
605 renderMap(driver, SceneManager->getSceneNodeRenderPass());
608 virtual const core::aabbox3d<f32>& getBoundingBox() const
613 void renderMap(video::IVideoDriver* driver, s32 pass);
616 Methods for setting temporary modifications to nodes for
619 Returns true if something changed.
621 All blocks whose mesh could have been changed are inserted
624 bool setTempMod(v3s16 p, NodeMod mod,
625 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
626 bool clearTempMod(v3s16 p,
627 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
628 // Efficient implementation needs a cache of TempMods
629 //void clearTempMods();
631 // For debug printing
632 virtual void PrintInfo(std::ostream &out);
637 core::aabbox3d<f32> m_box;
639 // This is the master heightmap mesh
640 //scene::SMesh *mesh;
643 MapDrawControl &m_control;
648 class MapVoxelManipulator : public VoxelManipulator
651 MapVoxelManipulator(Map *map);
652 virtual ~MapVoxelManipulator();
656 VoxelManipulator::clear();
657 m_loaded_blocks.clear();
660 virtual void emerge(VoxelArea a, s32 caller_id=-1);
662 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
668 value = block existed when loaded
670 core::map<v3s16, bool> m_loaded_blocks;
673 class ManualMapVoxelManipulator : public MapVoxelManipulator
676 ManualMapVoxelManipulator(Map *map);
677 virtual ~ManualMapVoxelManipulator();
679 virtual void emerge(VoxelArea a, s32 caller_id=-1);
681 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
683 // This is much faster with big chunks of generated data
684 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);