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"
38 #include "mapsector.h"
39 #include "constants.h"
43 #define MAPTYPE_BASE 0
44 #define MAPTYPE_SERVER 1
45 #define MAPTYPE_CLIENT 2
47 class Map : public NodeContainer
51 Map(std::ostream &dout);
54 virtual u16 nodeContainerId() const
56 return NODECONTAINER_ID_MAP;
59 virtual s32 mapType() const
65 Drop (client) or delete (server) the map.
72 void updateCamera(v3f pos, v3f dir)
74 JMutexAutoLock lock(m_camera_mutex);
75 m_camera_position = pos;
76 m_camera_direction = dir;
79 static core::aabbox3d<f32> getNodeBox(v3s16 p)
81 return core::aabbox3d<f32>(
82 (float)p.X * BS - 0.5*BS,
83 (float)p.Y * BS - 0.5*BS,
84 (float)p.Z * BS - 0.5*BS,
85 (float)p.X * BS + 0.5*BS,
86 (float)p.Y * BS + 0.5*BS,
87 (float)p.Z * BS + 0.5*BS
91 // On failure returns NULL
92 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
93 // On failure returns NULL
94 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
95 // On failure throws InvalidPositionException
96 MapSector * getSectorNoGenerate(v2s16 p2d);
97 // Gets an existing sector or creates an empty one
98 //MapSector * getSectorCreate(v2s16 p2d);
101 This is overloaded by ClientMap and ServerMap to allow
102 their differing fetch methods.
104 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
105 virtual MapSector * emergeSector(v2s16 p,
106 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
108 // Returns InvalidPositionException if not found
109 MapBlock * getBlockNoCreate(v3s16 p);
110 // Returns NULL if not found
111 MapBlock * getBlockNoCreateNoEx(v3s16 p);
112 // Gets an existing block or creates an empty one
113 //MapBlock * getBlockCreate(v3s16 p);
115 // Returns InvalidPositionException if not found
116 f32 getGroundHeight(v2s16 p, bool generate=false);
117 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
119 // Returns InvalidPositionException if not found
120 bool isNodeUnderground(v3s16 p);
122 // virtual from NodeContainer
123 bool isValidPosition(v3s16 p)
125 v3s16 blockpos = getNodeBlockPos(p);
128 blockref = getBlockNoCreate(blockpos);
130 catch(InvalidPositionException &e)
135 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
136 bool is_valid = blockref->isValidPosition(relpos);
140 // virtual from NodeContainer
141 // throws InvalidPositionException if not found
142 MapNode getNode(v3s16 p)
144 v3s16 blockpos = getNodeBlockPos(p);
145 MapBlock * blockref = getBlockNoCreate(blockpos);
146 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
148 return blockref->getNodeNoCheck(relpos);
151 // virtual from NodeContainer
152 // throws InvalidPositionException if not found
153 void setNode(v3s16 p, MapNode & n)
155 v3s16 blockpos = getNodeBlockPos(p);
156 MapBlock * blockref = getBlockNoCreate(blockpos);
157 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
158 blockref->setNodeNoCheck(relpos, n);
161 /*MapNode getNodeGenerate(v3s16 p)
163 v3s16 blockpos = getNodeBlockPos(p);
164 MapBlock * blockref = getBlock(blockpos);
165 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
167 return blockref->getNode(relpos);
170 /*void setNodeGenerate(v3s16 p, MapNode & n)
172 v3s16 blockpos = getNodeBlockPos(p);
173 MapBlock * blockref = getBlock(blockpos);
174 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
175 blockref->setNode(relpos, n);
178 void unspreadLight(enum LightBank bank,
179 core::map<v3s16, u8> & from_nodes,
180 core::map<v3s16, bool> & light_sources,
181 core::map<v3s16, MapBlock*> & modified_blocks);
183 void unLightNeighbors(enum LightBank bank,
184 v3s16 pos, u8 lightwas,
185 core::map<v3s16, bool> & light_sources,
186 core::map<v3s16, MapBlock*> & modified_blocks);
188 void spreadLight(enum LightBank bank,
189 core::map<v3s16, bool> & from_nodes,
190 core::map<v3s16, MapBlock*> & modified_blocks);
192 void lightNeighbors(enum LightBank bank,
194 core::map<v3s16, MapBlock*> & modified_blocks);
196 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
198 s16 propagateSunlight(v3s16 start,
199 core::map<v3s16, MapBlock*> & modified_blocks);
201 void updateLighting(enum LightBank bank,
202 core::map<v3s16, MapBlock*> & a_blocks,
203 core::map<v3s16, MapBlock*> & modified_blocks);
205 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
206 core::map<v3s16, MapBlock*> & modified_blocks);
209 These handle lighting but not faces.
211 void addNodeAndUpdate(v3s16 p, MapNode n,
212 core::map<v3s16, MapBlock*> &modified_blocks);
213 void removeNodeAndUpdate(v3s16 p,
214 core::map<v3s16, MapBlock*> &modified_blocks);
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;
273 This is the only map class that is able to generate map.
276 class ServerMap : public Map
280 savedir: directory to which map data should be saved
282 ServerMap(std::string savedir);
287 return MAPTYPE_SERVER;
294 // Returns the position of the chunk where the sector is in
295 v2s16 sector_to_chunk(v2s16 sectorpos)
297 sectorpos.X += m_chunksize / 2;
298 sectorpos.Y += m_chunksize / 2;
299 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
303 // Returns the position of the (0,0) sector of the chunk
304 v2s16 chunk_to_sector(v2s16 chunkpos)
307 chunkpos.X * m_chunksize,
308 chunkpos.Y * m_chunksize
310 sectorpos.X -= m_chunksize / 2;
311 sectorpos.Y -= m_chunksize / 2;
318 MapChunk *getChunk(v2s16 chunkpos)
320 core::map<v2s16, MapChunk*>::Node *n;
321 n = m_chunks.find(chunkpos);
324 return n->getValue();
328 True if the chunk and its neighbors are fully generated.
329 It means the chunk will not be touched in the future by the
330 generator. If false, generateChunk will make it true.
332 bool chunkNonVolatile(v2s16 chunkpos)
334 /*for(s16 x=-1; x<=1; x++)
335 for(s16 y=-1; y<=1; y++)*/
339 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
340 MapChunk *chunk = getChunk(chunkpos);
343 if(chunk->getGenLevel() != GENERATED_FULLY)
352 All chunks touching this one can be altered also.
354 MapChunk* generateChunkRaw(v2s16 chunkpos,
355 core::map<v3s16, MapBlock*> &changed_blocks,
359 Generate a chunk and its neighbors so that it won't be touched
362 MapChunk* generateChunk(v2s16 chunkpos,
363 core::map<v3s16, MapBlock*> &changed_blocks);
368 This is mainly called by generateChunkRaw.
370 //ServerMapSector * generateSector(v2s16 p);
373 Get a sector from somewhere.
375 - Check disk (loads blocks also)
378 ServerMapSector * createSector(v2s16 p);
381 Get a sector from somewhere.
383 - Check disk (loads blocks also)
386 MapSector * emergeSector(v2s16 p,
387 core::map<v3s16, MapBlock*> &changed_blocks);
389 MapSector * emergeSector(v2s16 p)
391 core::map<v3s16, MapBlock*> changed_blocks;
392 return emergeSector(p, changed_blocks);
395 MapBlock * generateBlock(
397 MapBlock *original_dummy,
398 ServerMapSector *sector,
399 core::map<v3s16, MapBlock*> &changed_blocks,
400 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
404 Get a block from somewhere.
408 MapBlock * createBlock(v3s16 p);
411 only_from_disk, changed_blocks and lighting_invalidated_blocks
412 are not properly used by the new map generator.
414 MapBlock * emergeBlock(
417 core::map<v3s16, MapBlock*> &changed_blocks,
418 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
423 Forcefully get a block from somewhere.
426 - InvalidPositionException: possible if only_from_disk==true
429 - All already existing blocks that were modified are added.
430 - If found on disk, nothing will be added.
431 - If generated, the new block will not be included.
433 lighting_invalidated_blocks:
434 - All blocks that have heavy-to-calculate lighting changes
436 - updateLighting() should be called for these.
438 - A block that is in changed_blocks may not be in
439 lighting_invalidated_blocks.
441 MapBlock * emergeBlock(
444 core::map<v3s16, MapBlock*> &changed_blocks,
445 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
450 Misc. helper functions for fiddling with directory and file
453 void createDir(std::string path);
454 void createSaveDir();
455 // returns something like "xxxxxxxx"
456 std::string getSectorSubDir(v2s16 pos);
457 // returns something like "map/sectors/xxxxxxxx"
458 std::string getSectorDir(v2s16 pos);
459 std::string createSectorDir(v2s16 pos);
460 // dirname: final directory name
461 v2s16 getSectorPos(std::string dirname);
462 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
464 void save(bool only_changed);
467 // Saves map seed and possibly other stuff
471 void saveChunkMeta();
472 void loadChunkMeta();
474 // The sector mutex should be locked when calling most of these
476 // This only saves sector-specific data such as the heightmap
478 // DEPRECATED? Sectors have no metadata anymore.
479 void saveSectorMeta(ServerMapSector *sector);
480 MapSector* loadSectorMeta(std::string dirname);
482 // Full load of a sector including all blocks.
483 // returns true on success, false on failure.
484 bool loadSectorFull(v2s16 p2d);
485 // If sector is not found in memory, try to load it from disk.
486 // Returns true if sector now resides in memory
487 //bool deFlushSector(v2s16 p2d);
489 void saveBlock(MapBlock *block);
490 // This will generate a sector with getSector if not found.
491 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
493 // Gets from master heightmap
495 void getSectorCorners(v2s16 p2d, s16 *corners);
497 // For debug printing
498 virtual void PrintInfo(std::ostream &out);
500 bool isSavingEnabled(){ return m_map_saving_enabled; }
503 // Seed used for all kinds of randomness
506 std::string m_savedir;
507 bool m_map_saving_enabled;
509 // Chunk size in MapSectors
512 core::map<v2s16, MapChunk*> m_chunks;
521 struct MapDrawControl
526 wanted_max_blocks(0),
529 blocks_would_have_drawn(0)
532 // Overrides limits by drawing everything
534 // Wanted drawing range
536 // Maximum number of blocks to draw
537 u32 wanted_max_blocks;
538 // Blocks in this range are drawn regardless of number of blocks drawn
539 float wanted_min_range;
540 // Number of blocks rendered is written here by the renderer
542 // Number of blocks that would have been drawn in wanted_range
543 u32 blocks_would_have_drawn;
551 This is the only map class that is able to render itself on screen.
554 class ClientMap : public Map, public scene::ISceneNode
559 MapDrawControl &control,
560 scene::ISceneNode* parent,
561 scene::ISceneManager* mgr,
569 return MAPTYPE_CLIENT;
578 Forcefully get a sector from somewhere
580 MapSector * emergeSector(v2s16 p);
582 void deSerializeSector(v2s16 p2d, std::istream &is);
588 virtual void OnRegisterSceneNode();
590 virtual void render()
592 video::IVideoDriver* driver = SceneManager->getVideoDriver();
593 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
594 renderMap(driver, SceneManager->getSceneNodeRenderPass());
597 virtual const core::aabbox3d<f32>& getBoundingBox() const
602 void renderMap(video::IVideoDriver* driver, s32 pass);
605 Methods for setting temporary modifications to nodes for
608 Returns true if something changed.
610 All blocks whose mesh could have been changed are inserted
613 bool setTempMod(v3s16 p, NodeMod mod,
614 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
615 bool clearTempMod(v3s16 p,
616 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
617 // Efficient implementation needs a cache of TempMods
618 //void clearTempMods();
620 void expireMeshes(bool only_daynight_diffed);
623 Update the faces of the given block and blocks on the
626 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
628 // Update meshes that touch the node
629 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
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);