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 enum MapEditEventType{
55 MapEditEventType type;
58 core::map<v3s16, bool> modified_blocks;
59 u16 already_known_by_peer;
63 already_known_by_peer(0)
67 MapEditEvent * clone()
69 MapEditEvent *event = new MapEditEvent();
73 for(core::map<v3s16, bool>::Iterator
74 i = modified_blocks.getIterator();
75 i.atEnd()==false; i++)
77 v3s16 p = i.getNode()->getKey();
78 bool v = i.getNode()->getValue();
79 event->modified_blocks.insert(p, v);
85 class MapEventReceiver
88 // event shall be deleted by caller after the call.
89 virtual void onMapEditEvent(MapEditEvent *event) = 0;
92 class Map : public NodeContainer
96 Map(std::ostream &dout);
99 virtual u16 nodeContainerId() const
101 return NODECONTAINER_ID_MAP;
104 virtual s32 mapType() const
110 Drop (client) or delete (server) the map.
117 void addEventReceiver(MapEventReceiver *event_receiver);
118 void removeEventReceiver(MapEventReceiver *event_receiver);
119 // event shall be deleted by caller after the call.
120 void dispatchEvent(MapEditEvent *event);
122 // On failure returns NULL
123 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
124 // On failure returns NULL
125 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
126 // On failure throws InvalidPositionException
127 MapSector * getSectorNoGenerate(v2s16 p2d);
128 // Gets an existing sector or creates an empty one
129 //MapSector * getSectorCreate(v2s16 p2d);
132 This is overloaded by ClientMap and ServerMap to allow
133 their differing fetch methods.
135 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
136 virtual MapSector * emergeSector(v2s16 p,
137 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
139 // Returns InvalidPositionException if not found
140 MapBlock * getBlockNoCreate(v3s16 p);
141 // Returns NULL if not found
142 MapBlock * getBlockNoCreateNoEx(v3s16 p);
143 // Gets an existing block or creates an empty one
144 //MapBlock * getBlockCreate(v3s16 p);
146 // Returns InvalidPositionException if not found
147 bool isNodeUnderground(v3s16 p);
149 // virtual from NodeContainer
150 bool isValidPosition(v3s16 p)
152 v3s16 blockpos = getNodeBlockPos(p);
155 blockref = getBlockNoCreate(blockpos);
157 catch(InvalidPositionException &e)
162 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
163 bool is_valid = blockref->isValidPosition(relpos);
167 // virtual from NodeContainer
168 // throws InvalidPositionException if not found
169 MapNode getNode(v3s16 p)
171 v3s16 blockpos = getNodeBlockPos(p);
172 MapBlock * blockref = getBlockNoCreate(blockpos);
173 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
175 return blockref->getNodeNoCheck(relpos);
178 // virtual from NodeContainer
179 // throws InvalidPositionException if not found
180 void setNode(v3s16 p, MapNode & n)
182 v3s16 blockpos = getNodeBlockPos(p);
183 MapBlock * blockref = getBlockNoCreate(blockpos);
184 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
185 blockref->setNodeNoCheck(relpos, n);
188 // Returns a CONTENT_IGNORE node if not found
189 MapNode getNodeNoEx(v3s16 p)
192 v3s16 blockpos = getNodeBlockPos(p);
193 MapBlock * blockref = getBlockNoCreate(blockpos);
194 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
196 return blockref->getNodeNoCheck(relpos);
198 catch(InvalidPositionException &e)
200 return MapNode(CONTENT_IGNORE);
204 void unspreadLight(enum LightBank bank,
205 core::map<v3s16, u8> & from_nodes,
206 core::map<v3s16, bool> & light_sources,
207 core::map<v3s16, MapBlock*> & modified_blocks);
209 void unLightNeighbors(enum LightBank bank,
210 v3s16 pos, u8 lightwas,
211 core::map<v3s16, bool> & light_sources,
212 core::map<v3s16, MapBlock*> & modified_blocks);
214 void spreadLight(enum LightBank bank,
215 core::map<v3s16, bool> & from_nodes,
216 core::map<v3s16, MapBlock*> & modified_blocks);
218 void lightNeighbors(enum LightBank bank,
220 core::map<v3s16, MapBlock*> & modified_blocks);
222 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
224 s16 propagateSunlight(v3s16 start,
225 core::map<v3s16, MapBlock*> & modified_blocks);
227 void updateLighting(enum LightBank bank,
228 core::map<v3s16, MapBlock*> & a_blocks,
229 core::map<v3s16, MapBlock*> & modified_blocks);
231 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
232 core::map<v3s16, MapBlock*> & modified_blocks);
235 These handle lighting but not faces.
237 void addNodeAndUpdate(v3s16 p, MapNode n,
238 core::map<v3s16, MapBlock*> &modified_blocks);
239 void removeNodeAndUpdate(v3s16 p,
240 core::map<v3s16, MapBlock*> &modified_blocks);
243 Wrappers for the latter ones.
245 Return true if succeeded, false if not.
247 bool addNodeWithEvent(v3s16 p, MapNode n);
248 bool removeNodeWithEvent(v3s16 p);
251 Takes the blocks at the edges into account
253 bool dayNightDiffed(v3s16 blockpos);
255 //core::aabbox3d<s16> getDisplayedBlockArea();
257 //bool updateChangedVisibleArea();
259 virtual void save(bool only_changed){assert(0);};
264 void timerUpdate(float dtime);
266 // Takes cache into account
267 // sector mutex should be locked when calling
268 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
270 // Returns count of deleted sectors
271 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
272 core::list<v3s16> *deleted_blocks=NULL);
274 // For debug printing
275 virtual void PrintInfo(std::ostream &out);
277 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
285 std::ostream &m_dout;
287 core::map<MapEventReceiver*, bool> m_event_receivers;
289 // Mutex is important because on client map is accessed asynchronously
290 core::map<v2s16, MapSector*> m_sectors;
291 JMutex m_sector_mutex;
293 // Be sure to set this to NULL when the cached sector is deleted
294 MapSector *m_sector_cache;
295 v2s16 m_sector_cache_p;
297 //WrapperHeightmap m_hwrapper;
299 // Queued transforming water nodes
300 UniqueQueue<v3s16> m_transforming_liquid;
306 This is the only map class that is able to generate map.
309 class ServerMap : public Map
313 savedir: directory to which map data should be saved
315 ServerMap(std::string savedir);
320 return MAPTYPE_SERVER;
327 // Returns the position of the chunk where the sector is in
328 v2s16 sector_to_chunk(v2s16 sectorpos)
330 sectorpos.X += m_chunksize / 2;
331 sectorpos.Y += m_chunksize / 2;
332 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
336 // Returns the position of the (0,0) sector of the chunk
337 v2s16 chunk_to_sector(v2s16 chunkpos)
340 chunkpos.X * m_chunksize,
341 chunkpos.Y * m_chunksize
343 sectorpos.X -= m_chunksize / 2;
344 sectorpos.Y -= m_chunksize / 2;
351 MapChunk *getChunk(v2s16 chunkpos)
353 core::map<v2s16, MapChunk*>::Node *n;
354 n = m_chunks.find(chunkpos);
357 return n->getValue();
361 True if the chunk and its neighbors are fully generated.
362 It means the chunk will not be touched in the future by the
363 generator. If false, generateChunk will make it true.
365 bool chunkNonVolatile(v2s16 chunkpos)
367 /*for(s16 x=-1; x<=1; x++)
368 for(s16 y=-1; y<=1; y++)*/
372 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
373 MapChunk *chunk = getChunk(chunkpos);
376 if(chunk->getGenLevel() != GENERATED_FULLY)
385 All chunks touching this one can be altered also.
387 MapChunk* generateChunkRaw(v2s16 chunkpos,
388 core::map<v3s16, MapBlock*> &changed_blocks,
392 Generate a chunk and its neighbors so that it won't be touched
395 MapChunk* generateChunk(v2s16 chunkpos,
396 core::map<v3s16, MapBlock*> &changed_blocks);
401 This is mainly called by generateChunkRaw.
403 //ServerMapSector * generateSector(v2s16 p);
406 Get a sector from somewhere.
408 - Check disk (loads blocks also)
411 ServerMapSector * createSector(v2s16 p);
414 Get a sector from somewhere.
416 - Check disk (loads blocks also)
419 MapSector * emergeSector(v2s16 p,
420 core::map<v3s16, MapBlock*> &changed_blocks);
422 MapSector * emergeSector(v2s16 p)
424 core::map<v3s16, MapBlock*> changed_blocks;
425 return emergeSector(p, changed_blocks);
428 MapBlock * generateBlock(
430 MapBlock *original_dummy,
431 ServerMapSector *sector,
432 core::map<v3s16, MapBlock*> &changed_blocks,
433 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
437 Get a block from somewhere.
441 MapBlock * createBlock(v3s16 p);
444 only_from_disk, changed_blocks and lighting_invalidated_blocks
445 are not properly used by the new map generator.
447 MapBlock * emergeBlock(
450 core::map<v3s16, MapBlock*> &changed_blocks,
451 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
456 Forcefully get a block from somewhere.
459 - InvalidPositionException: possible if only_from_disk==true
462 - All already existing blocks that were modified are added.
463 - If found on disk, nothing will be added.
464 - If generated, the new block will not be included.
466 lighting_invalidated_blocks:
467 - All blocks that have heavy-to-calculate lighting changes
469 - updateLighting() should be called for these.
471 - A block that is in changed_blocks may not be in
472 lighting_invalidated_blocks.
474 MapBlock * emergeBlock(
477 core::map<v3s16, MapBlock*> &changed_blocks,
478 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
482 // Helper for placing objects on ground level
483 s16 findGroundLevel(v2s16 p2d);
486 Misc. helper functions for fiddling with directory and file
489 void createDir(std::string path);
490 void createSaveDir();
491 // returns something like "xxxxxxxx"
492 std::string getSectorSubDir(v2s16 pos);
493 // returns something like "map/sectors/xxxxxxxx"
494 std::string getSectorDir(v2s16 pos);
495 std::string createSectorDir(v2s16 pos);
496 // dirname: final directory name
497 v2s16 getSectorPos(std::string dirname);
498 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
500 void save(bool only_changed);
503 // Saves map seed and possibly other stuff
507 void saveChunkMeta();
508 void loadChunkMeta();
510 // The sector mutex should be locked when calling most of these
512 // This only saves sector-specific data such as the heightmap
514 // DEPRECATED? Sectors have no metadata anymore.
515 void saveSectorMeta(ServerMapSector *sector);
516 MapSector* loadSectorMeta(std::string dirname);
518 // Full load of a sector including all blocks.
519 // returns true on success, false on failure.
520 bool loadSectorFull(v2s16 p2d);
521 // If sector is not found in memory, try to load it from disk.
522 // Returns true if sector now resides in memory
523 //bool deFlushSector(v2s16 p2d);
525 void saveBlock(MapBlock *block);
526 // This will generate a sector with getSector if not found.
527 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
529 // For debug printing
530 virtual void PrintInfo(std::ostream &out);
532 bool isSavingEnabled(){ return m_map_saving_enabled; }
535 // Seed used for all kinds of randomness
538 std::string m_savedir;
539 bool m_map_saving_enabled;
541 // Chunk size in MapSectors
544 core::map<v2s16, MapChunk*> m_chunks;
553 struct MapDrawControl
558 wanted_max_blocks(0),
561 blocks_would_have_drawn(0)
564 // Overrides limits by drawing everything
566 // Wanted drawing range
568 // Maximum number of blocks to draw
569 u32 wanted_max_blocks;
570 // Blocks in this range are drawn regardless of number of blocks drawn
571 float wanted_min_range;
572 // Number of blocks rendered is written here by the renderer
574 // Number of blocks that would have been drawn in wanted_range
575 u32 blocks_would_have_drawn;
583 This is the only map class that is able to render itself on screen.
586 class ClientMap : public Map, public scene::ISceneNode
591 MapDrawControl &control,
592 scene::ISceneNode* parent,
593 scene::ISceneManager* mgr,
601 return MAPTYPE_CLIENT;
609 void updateCamera(v3f pos, v3f dir)
611 JMutexAutoLock lock(m_camera_mutex);
612 m_camera_position = pos;
613 m_camera_direction = dir;
617 Forcefully get a sector from somewhere
619 MapSector * emergeSector(v2s16 p);
621 void deSerializeSector(v2s16 p2d, std::istream &is);
627 virtual void OnRegisterSceneNode();
629 virtual void render()
631 video::IVideoDriver* driver = SceneManager->getVideoDriver();
632 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
633 renderMap(driver, SceneManager->getSceneNodeRenderPass());
636 virtual const core::aabbox3d<f32>& getBoundingBox() const
641 void renderMap(video::IVideoDriver* driver, s32 pass);
644 Methods for setting temporary modifications to nodes for
647 Returns true if something changed.
649 All blocks whose mesh could have been changed are inserted
652 bool setTempMod(v3s16 p, NodeMod mod,
653 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
654 bool clearTempMod(v3s16 p,
655 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
656 // Efficient implementation needs a cache of TempMods
657 //void clearTempMods();
659 void expireMeshes(bool only_daynight_diffed);
662 Update the faces of the given block and blocks on the
665 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
667 // Update meshes that touch the node
668 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
670 // For debug printing
671 virtual void PrintInfo(std::ostream &out);
676 core::aabbox3d<f32> m_box;
678 // This is the master heightmap mesh
679 //scene::SMesh *mesh;
682 MapDrawControl &m_control;
684 v3f m_camera_position;
685 v3f m_camera_direction;
686 JMutex m_camera_mutex;
692 class MapVoxelManipulator : public VoxelManipulator
695 MapVoxelManipulator(Map *map);
696 virtual ~MapVoxelManipulator();
700 VoxelManipulator::clear();
701 m_loaded_blocks.clear();
704 virtual void emerge(VoxelArea a, s32 caller_id=-1);
706 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
712 value = block existed when loaded
714 core::map<v3s16, bool> m_loaded_blocks;
717 class ManualMapVoxelManipulator : public MapVoxelManipulator
720 ManualMapVoxelManipulator(Map *map);
721 virtual ~ManualMapVoxelManipulator();
723 virtual void emerge(VoxelArea a, s32 caller_id=-1);
725 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
727 // This is much faster with big chunks of generated data
728 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);