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"
44 Some exposed functions
47 double base_rock_level_2d(u64 seed, v2f p);
52 #define MAPTYPE_BASE 0
53 #define MAPTYPE_SERVER 1
54 #define MAPTYPE_CLIENT 2
56 enum MapEditEventType{
64 MapEditEventType type;
67 core::map<v3s16, bool> modified_blocks;
68 u16 already_known_by_peer;
72 already_known_by_peer(0)
76 MapEditEvent * clone()
78 MapEditEvent *event = new MapEditEvent();
82 for(core::map<v3s16, bool>::Iterator
83 i = modified_blocks.getIterator();
84 i.atEnd()==false; i++)
86 v3s16 p = i.getNode()->getKey();
87 bool v = i.getNode()->getValue();
88 event->modified_blocks.insert(p, v);
94 class MapEventReceiver
97 // event shall be deleted by caller after the call.
98 virtual void onMapEditEvent(MapEditEvent *event) = 0;
101 class Map : public NodeContainer
105 Map(std::ostream &dout);
108 virtual u16 nodeContainerId() const
110 return NODECONTAINER_ID_MAP;
113 virtual s32 mapType() const
119 Drop (client) or delete (server) the map.
126 void addEventReceiver(MapEventReceiver *event_receiver);
127 void removeEventReceiver(MapEventReceiver *event_receiver);
128 // event shall be deleted by caller after the call.
129 void dispatchEvent(MapEditEvent *event);
131 // On failure returns NULL
132 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
133 // On failure returns NULL
134 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
135 // On failure throws InvalidPositionException
136 MapSector * getSectorNoGenerate(v2s16 p2d);
137 // Gets an existing sector or creates an empty one
138 //MapSector * getSectorCreate(v2s16 p2d);
141 This is overloaded by ClientMap and ServerMap to allow
142 their differing fetch methods.
144 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
145 virtual MapSector * emergeSector(v2s16 p,
146 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
148 // Returns InvalidPositionException if not found
149 MapBlock * getBlockNoCreate(v3s16 p);
150 // Returns NULL if not found
151 MapBlock * getBlockNoCreateNoEx(v3s16 p);
152 // Gets an existing block or creates an empty one
153 //MapBlock * getBlockCreate(v3s16 p);
155 // Returns InvalidPositionException if not found
156 bool isNodeUnderground(v3s16 p);
158 // virtual from NodeContainer
159 bool isValidPosition(v3s16 p)
161 v3s16 blockpos = getNodeBlockPos(p);
164 blockref = getBlockNoCreate(blockpos);
166 catch(InvalidPositionException &e)
171 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
172 bool is_valid = blockref->isValidPosition(relpos);
176 // virtual from NodeContainer
177 // throws InvalidPositionException if not found
178 MapNode getNode(v3s16 p)
180 v3s16 blockpos = getNodeBlockPos(p);
181 MapBlock * blockref = getBlockNoCreate(blockpos);
182 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
184 return blockref->getNodeNoCheck(relpos);
187 // virtual from NodeContainer
188 // throws InvalidPositionException if not found
189 void setNode(v3s16 p, MapNode & n)
191 v3s16 blockpos = getNodeBlockPos(p);
192 MapBlock * blockref = getBlockNoCreate(blockpos);
193 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
194 blockref->setNodeNoCheck(relpos, n);
197 // Returns a CONTENT_IGNORE node if not found
198 MapNode getNodeNoEx(v3s16 p)
201 v3s16 blockpos = getNodeBlockPos(p);
202 MapBlock * blockref = getBlockNoCreate(blockpos);
203 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
205 return blockref->getNodeNoCheck(relpos);
207 catch(InvalidPositionException &e)
209 return MapNode(CONTENT_IGNORE);
213 void unspreadLight(enum LightBank bank,
214 core::map<v3s16, u8> & from_nodes,
215 core::map<v3s16, bool> & light_sources,
216 core::map<v3s16, MapBlock*> & modified_blocks);
218 void unLightNeighbors(enum LightBank bank,
219 v3s16 pos, u8 lightwas,
220 core::map<v3s16, bool> & light_sources,
221 core::map<v3s16, MapBlock*> & modified_blocks);
223 void spreadLight(enum LightBank bank,
224 core::map<v3s16, bool> & from_nodes,
225 core::map<v3s16, MapBlock*> & modified_blocks);
227 void lightNeighbors(enum LightBank bank,
229 core::map<v3s16, MapBlock*> & modified_blocks);
231 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
233 s16 propagateSunlight(v3s16 start,
234 core::map<v3s16, MapBlock*> & modified_blocks);
236 void updateLighting(enum LightBank bank,
237 core::map<v3s16, MapBlock*> & a_blocks,
238 core::map<v3s16, MapBlock*> & modified_blocks);
240 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
241 core::map<v3s16, MapBlock*> & modified_blocks);
244 These handle lighting but not faces.
246 void addNodeAndUpdate(v3s16 p, MapNode n,
247 core::map<v3s16, MapBlock*> &modified_blocks);
248 void removeNodeAndUpdate(v3s16 p,
249 core::map<v3s16, MapBlock*> &modified_blocks);
252 Wrappers for the latter ones.
254 Return true if succeeded, false if not.
256 bool addNodeWithEvent(v3s16 p, MapNode n);
257 bool removeNodeWithEvent(v3s16 p);
260 Takes the blocks at the edges into account
262 bool dayNightDiffed(v3s16 blockpos);
264 //core::aabbox3d<s16> getDisplayedBlockArea();
266 //bool updateChangedVisibleArea();
268 virtual void save(bool only_changed){assert(0);};
273 void timerUpdate(float dtime);
275 // Takes cache into account
276 // sector mutex should be locked when calling
277 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
279 // Returns count of deleted sectors
280 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
281 core::list<v3s16> *deleted_blocks=NULL);
283 // For debug printing
284 virtual void PrintInfo(std::ostream &out);
286 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
294 std::ostream &m_dout;
296 core::map<MapEventReceiver*, bool> m_event_receivers;
298 // Mutex is important because on client map is accessed asynchronously
299 core::map<v2s16, MapSector*> m_sectors;
300 JMutex m_sector_mutex;
302 // Be sure to set this to NULL when the cached sector is deleted
303 MapSector *m_sector_cache;
304 v2s16 m_sector_cache_p;
306 //WrapperHeightmap m_hwrapper;
308 // Queued transforming water nodes
309 UniqueQueue<v3s16> m_transforming_liquid;
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);
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,
401 Generate a chunk and its neighbors so that it won't be touched
404 MapChunk* generateChunk(v2s16 chunkpos,
405 core::map<v3s16, MapBlock*> &changed_blocks);
410 This is mainly called by generateChunkRaw.
412 //ServerMapSector * generateSector(v2s16 p);
415 Get a sector from somewhere.
417 - Check disk (loads blocks also)
420 ServerMapSector * createSector(v2s16 p);
423 Get a sector from somewhere.
425 - Check disk (loads blocks also)
428 MapSector * emergeSector(v2s16 p,
429 core::map<v3s16, MapBlock*> &changed_blocks);
431 MapSector * emergeSector(v2s16 p)
433 core::map<v3s16, MapBlock*> changed_blocks;
434 return emergeSector(p, changed_blocks);
437 MapBlock * generateBlock(
439 MapBlock *original_dummy,
440 ServerMapSector *sector,
441 core::map<v3s16, MapBlock*> &changed_blocks,
442 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
446 Get a block from somewhere.
450 MapBlock * createBlock(v3s16 p);
453 only_from_disk, changed_blocks and lighting_invalidated_blocks
454 are not properly used by the new map generator.
456 MapBlock * emergeBlock(
459 core::map<v3s16, MapBlock*> &changed_blocks,
460 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
465 Forcefully get a block from somewhere.
468 - InvalidPositionException: possible if only_from_disk==true
471 - All already existing blocks that were modified are added.
472 - If found on disk, nothing will be added.
473 - If generated, the new block will not be included.
475 lighting_invalidated_blocks:
476 - All blocks that have heavy-to-calculate lighting changes
478 - updateLighting() should be called for these.
480 - A block that is in changed_blocks may not be in
481 lighting_invalidated_blocks.
483 MapBlock * emergeBlock(
486 core::map<v3s16, MapBlock*> &changed_blocks,
487 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
491 // Helper for placing objects on ground level
492 s16 findGroundLevel(v2s16 p2d);
495 Misc. helper functions for fiddling with directory and file
498 void createDir(std::string path);
499 void createSaveDir();
500 // returns something like "xxxxxxxx"
501 std::string getSectorSubDir(v2s16 pos);
502 // returns something like "map/sectors/xxxxxxxx"
503 std::string getSectorDir(v2s16 pos);
504 std::string createSectorDir(v2s16 pos);
505 // dirname: final directory name
506 v2s16 getSectorPos(std::string dirname);
507 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
509 void save(bool only_changed);
512 // Saves map seed and possibly other stuff
516 void saveChunkMeta();
517 void loadChunkMeta();
519 // The sector mutex should be locked when calling most of these
521 // This only saves sector-specific data such as the heightmap
523 // DEPRECATED? Sectors have no metadata anymore.
524 void saveSectorMeta(ServerMapSector *sector);
525 MapSector* loadSectorMeta(std::string dirname);
527 // Full load of a sector including all blocks.
528 // returns true on success, false on failure.
529 bool loadSectorFull(v2s16 p2d);
530 // If sector is not found in memory, try to load it from disk.
531 // Returns true if sector now resides in memory
532 //bool deFlushSector(v2s16 p2d);
534 void saveBlock(MapBlock *block);
535 // This will generate a sector with getSector if not found.
536 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
538 // For debug printing
539 virtual void PrintInfo(std::ostream &out);
541 bool isSavingEnabled(){ return m_map_saving_enabled; }
543 u64 getSeed(){ return m_seed; }
546 // Seed used for all kinds of randomness
549 std::string m_savedir;
550 bool m_map_saving_enabled;
552 // Chunk size in MapSectors
555 core::map<v2s16, MapChunk*> m_chunks;
564 struct MapDrawControl
569 wanted_max_blocks(0),
572 blocks_would_have_drawn(0)
575 // Overrides limits by drawing everything
577 // Wanted drawing range
579 // Maximum number of blocks to draw
580 u32 wanted_max_blocks;
581 // Blocks in this range are drawn regardless of number of blocks drawn
582 float wanted_min_range;
583 // Number of blocks rendered is written here by the renderer
585 // Number of blocks that would have been drawn in wanted_range
586 u32 blocks_would_have_drawn;
594 This is the only map class that is able to render itself on screen.
597 class ClientMap : public Map, public scene::ISceneNode
602 MapDrawControl &control,
603 scene::ISceneNode* parent,
604 scene::ISceneManager* mgr,
612 return MAPTYPE_CLIENT;
620 void updateCamera(v3f pos, v3f dir)
622 JMutexAutoLock lock(m_camera_mutex);
623 m_camera_position = pos;
624 m_camera_direction = dir;
628 Forcefully get a sector from somewhere
630 MapSector * emergeSector(v2s16 p);
632 void deSerializeSector(v2s16 p2d, std::istream &is);
638 virtual void OnRegisterSceneNode();
640 virtual void render()
642 video::IVideoDriver* driver = SceneManager->getVideoDriver();
643 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
644 renderMap(driver, SceneManager->getSceneNodeRenderPass());
647 virtual const core::aabbox3d<f32>& getBoundingBox() const
652 void renderMap(video::IVideoDriver* driver, s32 pass);
655 Methods for setting temporary modifications to nodes for
658 Returns true if something changed.
660 All blocks whose mesh could have been changed are inserted
663 bool setTempMod(v3s16 p, NodeMod mod,
664 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
665 bool clearTempMod(v3s16 p,
666 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
667 // Efficient implementation needs a cache of TempMods
668 //void clearTempMods();
670 void expireMeshes(bool only_daynight_diffed);
673 Update the faces of the given block and blocks on the
676 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
678 // Update meshes that touch the node
679 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
681 // For debug printing
682 virtual void PrintInfo(std::ostream &out);
687 core::aabbox3d<f32> m_box;
689 // This is the master heightmap mesh
690 //scene::SMesh *mesh;
693 MapDrawControl &m_control;
695 v3f m_camera_position;
696 v3f m_camera_direction;
697 JMutex m_camera_mutex;
703 class MapVoxelManipulator : public VoxelManipulator
706 MapVoxelManipulator(Map *map);
707 virtual ~MapVoxelManipulator();
711 VoxelManipulator::clear();
712 m_loaded_blocks.clear();
715 virtual void emerge(VoxelArea a, s32 caller_id=-1);
717 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
723 value = block existed when loaded
725 core::map<v3s16, bool> m_loaded_blocks;
728 class ManualMapVoxelManipulator : public MapVoxelManipulator
731 ManualMapVoxelManipulator(Map *map);
732 virtual ~ManualMapVoxelManipulator();
734 virtual void emerge(VoxelArea a, s32 caller_id=-1);
736 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
738 // This is much faster with big chunks of generated data
739 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);