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);
48 bool get_have_sand(u64 seed, v2f p);
53 #define MAPTYPE_BASE 0
54 #define MAPTYPE_SERVER 1
55 #define MAPTYPE_CLIENT 2
57 enum MapEditEventType{
65 MapEditEventType type;
68 core::map<v3s16, bool> modified_blocks;
69 u16 already_known_by_peer;
73 already_known_by_peer(0)
77 MapEditEvent * clone()
79 MapEditEvent *event = new MapEditEvent();
83 for(core::map<v3s16, bool>::Iterator
84 i = modified_blocks.getIterator();
85 i.atEnd()==false; i++)
87 v3s16 p = i.getNode()->getKey();
88 bool v = i.getNode()->getValue();
89 event->modified_blocks.insert(p, v);
95 class MapEventReceiver
98 // event shall be deleted by caller after the call.
99 virtual void onMapEditEvent(MapEditEvent *event) = 0;
102 class Map : public NodeContainer
106 Map(std::ostream &dout);
109 virtual u16 nodeContainerId() const
111 return NODECONTAINER_ID_MAP;
114 virtual s32 mapType() const
120 Drop (client) or delete (server) the map.
127 void addEventReceiver(MapEventReceiver *event_receiver);
128 void removeEventReceiver(MapEventReceiver *event_receiver);
129 // event shall be deleted by caller after the call.
130 void dispatchEvent(MapEditEvent *event);
132 // On failure returns NULL
133 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
134 // On failure returns NULL
135 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
136 // On failure throws InvalidPositionException
137 MapSector * getSectorNoGenerate(v2s16 p2d);
138 // Gets an existing sector or creates an empty one
139 //MapSector * getSectorCreate(v2s16 p2d);
142 This is overloaded by ClientMap and ServerMap to allow
143 their differing fetch methods.
145 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
146 virtual MapSector * emergeSector(v2s16 p,
147 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
149 // Returns InvalidPositionException if not found
150 MapBlock * getBlockNoCreate(v3s16 p);
151 // Returns NULL if not found
152 MapBlock * getBlockNoCreateNoEx(v3s16 p);
153 // Gets an existing block or creates an empty one
154 //MapBlock * getBlockCreate(v3s16 p);
156 // Returns InvalidPositionException if not found
157 bool isNodeUnderground(v3s16 p);
159 // virtual from NodeContainer
160 bool isValidPosition(v3s16 p)
162 v3s16 blockpos = getNodeBlockPos(p);
165 blockref = getBlockNoCreate(blockpos);
167 catch(InvalidPositionException &e)
172 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
173 bool is_valid = blockref->isValidPosition(relpos);
177 // virtual from NodeContainer
178 // throws InvalidPositionException if not found
179 MapNode getNode(v3s16 p)
181 v3s16 blockpos = getNodeBlockPos(p);
182 MapBlock * blockref = getBlockNoCreate(blockpos);
183 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
185 return blockref->getNodeNoCheck(relpos);
188 // virtual from NodeContainer
189 // throws InvalidPositionException if not found
190 void setNode(v3s16 p, MapNode & n)
192 v3s16 blockpos = getNodeBlockPos(p);
193 MapBlock * blockref = getBlockNoCreate(blockpos);
194 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
195 blockref->setNodeNoCheck(relpos, n);
198 // Returns a CONTENT_IGNORE node if not found
199 MapNode getNodeNoEx(v3s16 p)
202 v3s16 blockpos = getNodeBlockPos(p);
203 MapBlock * blockref = getBlockNoCreate(blockpos);
204 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
206 return blockref->getNodeNoCheck(relpos);
208 catch(InvalidPositionException &e)
210 return MapNode(CONTENT_IGNORE);
214 void unspreadLight(enum LightBank bank,
215 core::map<v3s16, u8> & from_nodes,
216 core::map<v3s16, bool> & light_sources,
217 core::map<v3s16, MapBlock*> & modified_blocks);
219 void unLightNeighbors(enum LightBank bank,
220 v3s16 pos, u8 lightwas,
221 core::map<v3s16, bool> & light_sources,
222 core::map<v3s16, MapBlock*> & modified_blocks);
224 void spreadLight(enum LightBank bank,
225 core::map<v3s16, bool> & from_nodes,
226 core::map<v3s16, MapBlock*> & modified_blocks);
228 void lightNeighbors(enum LightBank bank,
230 core::map<v3s16, MapBlock*> & modified_blocks);
232 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
234 s16 propagateSunlight(v3s16 start,
235 core::map<v3s16, MapBlock*> & modified_blocks);
237 void updateLighting(enum LightBank bank,
238 core::map<v3s16, MapBlock*> & a_blocks,
239 core::map<v3s16, MapBlock*> & modified_blocks);
241 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
242 core::map<v3s16, MapBlock*> & modified_blocks);
245 These handle lighting but not faces.
247 void addNodeAndUpdate(v3s16 p, MapNode n,
248 core::map<v3s16, MapBlock*> &modified_blocks);
249 void removeNodeAndUpdate(v3s16 p,
250 core::map<v3s16, MapBlock*> &modified_blocks);
253 Wrappers for the latter ones.
255 Return true if succeeded, false if not.
257 bool addNodeWithEvent(v3s16 p, MapNode n);
258 bool removeNodeWithEvent(v3s16 p);
261 Takes the blocks at the edges into account
263 bool dayNightDiffed(v3s16 blockpos);
265 //core::aabbox3d<s16> getDisplayedBlockArea();
267 //bool updateChangedVisibleArea();
269 virtual void save(bool only_changed){assert(0);};
274 void timerUpdate(float dtime);
276 // Takes cache into account
277 // sector mutex should be locked when calling
278 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
280 // Returns count of deleted sectors
281 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
282 core::list<v3s16> *deleted_blocks=NULL);
284 // For debug printing
285 virtual void PrintInfo(std::ostream &out);
287 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
295 std::ostream &m_dout;
297 core::map<MapEventReceiver*, bool> m_event_receivers;
299 // Mutex is important because on client map is accessed asynchronously
300 core::map<v2s16, MapSector*> m_sectors;
301 JMutex m_sector_mutex;
303 // Be sure to set this to NULL when the cached sector is deleted
304 MapSector *m_sector_cache;
305 v2s16 m_sector_cache_p;
307 //WrapperHeightmap m_hwrapper;
309 // Queued transforming water nodes
310 UniqueQueue<v3s16> m_transforming_liquid;
316 This is the only map class that is able to generate map.
319 class ServerMap : public Map
323 savedir: directory to which map data should be saved
325 ServerMap(std::string savedir);
330 return MAPTYPE_SERVER;
337 // Returns the position of the chunk where the sector is in
338 v2s16 sector_to_chunk(v2s16 sectorpos)
340 sectorpos.X += m_chunksize / 2;
341 sectorpos.Y += m_chunksize / 2;
342 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
346 // Returns the position of the (0,0) sector of the chunk
347 v2s16 chunk_to_sector(v2s16 chunkpos)
350 chunkpos.X * m_chunksize,
351 chunkpos.Y * m_chunksize
353 sectorpos.X -= m_chunksize / 2;
354 sectorpos.Y -= m_chunksize / 2;
361 MapChunk *getChunk(v2s16 chunkpos)
363 core::map<v2s16, MapChunk*>::Node *n;
364 n = m_chunks.find(chunkpos);
367 return n->getValue();
371 True if the chunk and its neighbors are fully generated.
372 It means the chunk will not be touched in the future by the
373 generator. If false, generateChunk will make it true.
375 bool chunkNonVolatile(v2s16 chunkpos)
377 /*for(s16 x=-1; x<=1; x++)
378 for(s16 y=-1; y<=1; y++)*/
382 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
383 MapChunk *chunk = getChunk(chunkpos);
386 if(chunk->getGenLevel() != GENERATED_FULLY)
395 All chunks touching this one can be altered also.
397 MapChunk* generateChunkRaw(v2s16 chunkpos,
398 core::map<v3s16, MapBlock*> &changed_blocks,
402 Generate a chunk and its neighbors so that it won't be touched
405 MapChunk* generateChunk(v2s16 chunkpos,
406 core::map<v3s16, MapBlock*> &changed_blocks);
411 This is mainly called by generateChunkRaw.
413 //ServerMapSector * generateSector(v2s16 p);
416 Get a sector from somewhere.
418 - Check disk (loads blocks also)
421 ServerMapSector * createSector(v2s16 p);
424 Get a sector from somewhere.
426 - Check disk (loads blocks also)
429 MapSector * emergeSector(v2s16 p,
430 core::map<v3s16, MapBlock*> &changed_blocks);
432 MapSector * emergeSector(v2s16 p)
434 core::map<v3s16, MapBlock*> changed_blocks;
435 return emergeSector(p, changed_blocks);
438 MapBlock * generateBlock(
440 MapBlock *original_dummy,
441 ServerMapSector *sector,
442 core::map<v3s16, MapBlock*> &changed_blocks,
443 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
447 Get a block from somewhere.
451 MapBlock * createBlock(v3s16 p);
454 only_from_disk, changed_blocks and lighting_invalidated_blocks
455 are not properly used by the new map generator.
457 MapBlock * emergeBlock(
460 core::map<v3s16, MapBlock*> &changed_blocks,
461 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
466 Forcefully get a block from somewhere.
469 - InvalidPositionException: possible if only_from_disk==true
472 - All already existing blocks that were modified are added.
473 - If found on disk, nothing will be added.
474 - If generated, the new block will not be included.
476 lighting_invalidated_blocks:
477 - All blocks that have heavy-to-calculate lighting changes
479 - updateLighting() should be called for these.
481 - A block that is in changed_blocks may not be in
482 lighting_invalidated_blocks.
484 MapBlock * emergeBlock(
487 core::map<v3s16, MapBlock*> &changed_blocks,
488 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
492 // Helper for placing objects on ground level
493 s16 findGroundLevel(v2s16 p2d);
496 Misc. helper functions for fiddling with directory and file
499 void createDir(std::string path);
500 void createSaveDir();
501 // returns something like "xxxxxxxx"
502 std::string getSectorSubDir(v2s16 pos);
503 // returns something like "map/sectors/xxxxxxxx"
504 std::string getSectorDir(v2s16 pos);
505 std::string createSectorDir(v2s16 pos);
506 // dirname: final directory name
507 v2s16 getSectorPos(std::string dirname);
508 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
510 void save(bool only_changed);
513 // Saves map seed and possibly other stuff
517 void saveChunkMeta();
518 void loadChunkMeta();
520 // The sector mutex should be locked when calling most of these
522 // This only saves sector-specific data such as the heightmap
524 // DEPRECATED? Sectors have no metadata anymore.
525 void saveSectorMeta(ServerMapSector *sector);
526 MapSector* loadSectorMeta(std::string dirname);
528 // Full load of a sector including all blocks.
529 // returns true on success, false on failure.
530 bool loadSectorFull(v2s16 p2d);
531 // If sector is not found in memory, try to load it from disk.
532 // Returns true if sector now resides in memory
533 //bool deFlushSector(v2s16 p2d);
535 void saveBlock(MapBlock *block);
536 // This will generate a sector with getSector if not found.
537 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
539 // For debug printing
540 virtual void PrintInfo(std::ostream &out);
542 bool isSavingEnabled(){ return m_map_saving_enabled; }
544 u64 getSeed(){ return m_seed; }
547 // Seed used for all kinds of randomness
550 std::string m_savedir;
551 bool m_map_saving_enabled;
553 // Chunk size in MapSectors
556 core::map<v2s16, MapChunk*> m_chunks;
565 struct MapDrawControl
570 wanted_max_blocks(0),
573 blocks_would_have_drawn(0)
576 // Overrides limits by drawing everything
578 // Wanted drawing range
580 // Maximum number of blocks to draw
581 u32 wanted_max_blocks;
582 // Blocks in this range are drawn regardless of number of blocks drawn
583 float wanted_min_range;
584 // Number of blocks rendered is written here by the renderer
586 // Number of blocks that would have been drawn in wanted_range
587 u32 blocks_would_have_drawn;
595 This is the only map class that is able to render itself on screen.
598 class ClientMap : public Map, public scene::ISceneNode
603 MapDrawControl &control,
604 scene::ISceneNode* parent,
605 scene::ISceneManager* mgr,
613 return MAPTYPE_CLIENT;
621 void updateCamera(v3f pos, v3f dir)
623 JMutexAutoLock lock(m_camera_mutex);
624 m_camera_position = pos;
625 m_camera_direction = dir;
629 Forcefully get a sector from somewhere
631 MapSector * emergeSector(v2s16 p);
633 void deSerializeSector(v2s16 p2d, std::istream &is);
639 virtual void OnRegisterSceneNode();
641 virtual void render()
643 video::IVideoDriver* driver = SceneManager->getVideoDriver();
644 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
645 renderMap(driver, SceneManager->getSceneNodeRenderPass());
648 virtual const core::aabbox3d<f32>& getBoundingBox() const
653 void renderMap(video::IVideoDriver* driver, s32 pass);
656 Methods for setting temporary modifications to nodes for
659 Returns true if something changed.
661 All blocks whose mesh could have been changed are inserted
664 bool setTempMod(v3s16 p, NodeMod mod,
665 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
666 bool clearTempMod(v3s16 p,
667 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
668 // Efficient implementation needs a cache of TempMods
669 //void clearTempMods();
671 void expireMeshes(bool only_daynight_diffed);
674 Update the faces of the given block and blocks on the
677 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
679 // Update meshes that touch the node
680 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
682 // For debug printing
683 virtual void PrintInfo(std::ostream &out);
688 core::aabbox3d<f32> m_box;
690 // This is the master heightmap mesh
691 //scene::SMesh *mesh;
694 MapDrawControl &m_control;
696 v3f m_camera_position;
697 v3f m_camera_direction;
698 JMutex m_camera_mutex;
704 class MapVoxelManipulator : public VoxelManipulator
707 MapVoxelManipulator(Map *map);
708 virtual ~MapVoxelManipulator();
712 VoxelManipulator::clear();
713 m_loaded_blocks.clear();
716 virtual void emerge(VoxelArea a, s32 caller_id=-1);
718 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
724 value = block existed when loaded
726 core::map<v3s16, bool> m_loaded_blocks;
729 class ManualMapVoxelManipulator : public MapVoxelManipulator
732 ManualMapVoxelManipulator(Map *map);
733 virtual ~ManualMapVoxelManipulator();
735 virtual void emerge(VoxelArea a, s32 caller_id=-1);
737 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
739 // This is much faster with big chunks of generated data
740 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);