3 Copyright (C) 2010-2011 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"
42 #include "nodemetadata.h"
44 #define MAPTYPE_BASE 0
45 #define MAPTYPE_SERVER 1
46 #define MAPTYPE_CLIENT 2
48 enum MapEditEventType{
49 // Node added (changed from air or something else to something)
51 // Node removed (changed to air)
53 // Node metadata of block changed (not knowing which node exactly)
54 // p stores block coordinate
55 MEET_BLOCK_NODE_METADATA_CHANGED,
62 MapEditEventType type;
65 core::map<v3s16, bool> modified_blocks;
66 u16 already_known_by_peer;
70 already_known_by_peer(0)
74 MapEditEvent * clone()
76 MapEditEvent *event = new MapEditEvent();
80 for(core::map<v3s16, bool>::Iterator
81 i = modified_blocks.getIterator();
82 i.atEnd()==false; i++)
84 v3s16 p = i.getNode()->getKey();
85 bool v = i.getNode()->getValue();
86 event->modified_blocks.insert(p, v);
92 class MapEventReceiver
95 // event shall be deleted by caller after the call.
96 virtual void onMapEditEvent(MapEditEvent *event) = 0;
99 class Map : public NodeContainer
103 Map(std::ostream &dout);
106 virtual u16 nodeContainerId() const
108 return NODECONTAINER_ID_MAP;
111 virtual s32 mapType() const
117 Drop (client) or delete (server) the map.
124 void addEventReceiver(MapEventReceiver *event_receiver);
125 void removeEventReceiver(MapEventReceiver *event_receiver);
126 // event shall be deleted by caller after the call.
127 void dispatchEvent(MapEditEvent *event);
129 // On failure returns NULL
130 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
131 // On failure returns NULL
132 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
133 // On failure throws InvalidPositionException
134 MapSector * getSectorNoGenerate(v2s16 p2d);
135 // Gets an existing sector or creates an empty one
136 //MapSector * getSectorCreate(v2s16 p2d);
139 This is overloaded by ClientMap and ServerMap to allow
140 their differing fetch methods.
142 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
143 virtual MapSector * emergeSector(v2s16 p,
144 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
146 // Returns InvalidPositionException if not found
147 MapBlock * getBlockNoCreate(v3s16 p);
148 // Returns NULL if not found
149 MapBlock * getBlockNoCreateNoEx(v3s16 p);
150 // Gets an existing block or creates an empty one
151 //MapBlock * getBlockCreate(v3s16 p);
153 // Returns InvalidPositionException if not found
154 bool isNodeUnderground(v3s16 p);
156 // virtual from NodeContainer
157 bool isValidPosition(v3s16 p)
159 v3s16 blockpos = getNodeBlockPos(p);
162 blockref = getBlockNoCreate(blockpos);
164 catch(InvalidPositionException &e)
169 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
170 bool is_valid = blockref->isValidPosition(relpos);
174 // virtual from NodeContainer
175 // throws InvalidPositionException if not found
176 MapNode getNode(v3s16 p)
178 v3s16 blockpos = getNodeBlockPos(p);
179 MapBlock * blockref = getBlockNoCreate(blockpos);
180 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
182 return blockref->getNodeNoCheck(relpos);
185 // virtual from NodeContainer
186 // throws InvalidPositionException if not found
187 void setNode(v3s16 p, MapNode & n)
189 v3s16 blockpos = getNodeBlockPos(p);
190 MapBlock * blockref = getBlockNoCreate(blockpos);
191 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
192 blockref->setNodeNoCheck(relpos, n);
195 // Returns a CONTENT_IGNORE node if not found
196 MapNode getNodeNoEx(v3s16 p)
199 v3s16 blockpos = getNodeBlockPos(p);
200 MapBlock * blockref = getBlockNoCreate(blockpos);
201 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
203 return blockref->getNodeNoCheck(relpos);
205 catch(InvalidPositionException &e)
207 return MapNode(CONTENT_IGNORE);
211 void unspreadLight(enum LightBank bank,
212 core::map<v3s16, u8> & from_nodes,
213 core::map<v3s16, bool> & light_sources,
214 core::map<v3s16, MapBlock*> & modified_blocks);
216 void unLightNeighbors(enum LightBank bank,
217 v3s16 pos, u8 lightwas,
218 core::map<v3s16, bool> & light_sources,
219 core::map<v3s16, MapBlock*> & modified_blocks);
221 void spreadLight(enum LightBank bank,
222 core::map<v3s16, bool> & from_nodes,
223 core::map<v3s16, MapBlock*> & modified_blocks);
225 void lightNeighbors(enum LightBank bank,
227 core::map<v3s16, MapBlock*> & modified_blocks);
229 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
231 s16 propagateSunlight(v3s16 start,
232 core::map<v3s16, MapBlock*> & modified_blocks);
234 void updateLighting(enum LightBank bank,
235 core::map<v3s16, MapBlock*> & a_blocks,
236 core::map<v3s16, MapBlock*> & modified_blocks);
238 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
239 core::map<v3s16, MapBlock*> & modified_blocks);
242 These handle lighting but not faces.
244 void addNodeAndUpdate(v3s16 p, MapNode n,
245 core::map<v3s16, MapBlock*> &modified_blocks);
246 void removeNodeAndUpdate(v3s16 p,
247 core::map<v3s16, MapBlock*> &modified_blocks);
250 Wrappers for the latter ones.
252 Return true if succeeded, false if not.
254 bool addNodeWithEvent(v3s16 p, MapNode n);
255 bool removeNodeWithEvent(v3s16 p);
258 Takes the blocks at the edges into account
260 bool dayNightDiffed(v3s16 blockpos);
262 //core::aabbox3d<s16> getDisplayedBlockArea();
264 //bool updateChangedVisibleArea();
266 virtual void save(bool only_changed){assert(0);};
271 void timerUpdate(float dtime);
273 // Takes cache into account
274 // sector mutex should be locked when calling
275 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
277 // Returns count of deleted sectors
278 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
279 core::list<v3s16> *deleted_blocks=NULL);
281 // For debug printing
282 virtual void PrintInfo(std::ostream &out);
284 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
288 These are basically coordinate wrappers to MapBlock
291 NodeMetadata* getNodeMetadata(v3s16 p);
292 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
293 void removeNodeMetadata(v3s16 p);
294 void nodeMetadataStep(float dtime,
295 core::map<v3s16, MapBlock*> &changed_blocks);
300 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
308 std::ostream &m_dout;
310 core::map<MapEventReceiver*, bool> m_event_receivers;
312 core::map<v2s16, MapSector*> m_sectors;
313 //JMutex m_sector_mutex;
315 // Be sure to set this to NULL when the cached sector is deleted
316 MapSector *m_sector_cache;
317 v2s16 m_sector_cache_p;
319 // Queued transforming water nodes
320 UniqueQueue<v3s16> m_transforming_liquid;
326 This is the only map class that is able to generate map.
329 struct ChunkMakeData;
331 class ServerMap : public Map
335 savedir: directory to which map data should be saved
337 ServerMap(std::string savedir);
342 return MAPTYPE_SERVER;
349 // Returns the position of the chunk where the sector is in
350 v2s16 sector_to_chunk(v2s16 sectorpos)
354 sectorpos.X += m_chunksize / 2;
355 sectorpos.Y += m_chunksize / 2;
356 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
360 // Returns the position of the (0,0) sector of the chunk
361 v2s16 chunk_to_sector(v2s16 chunkpos)
366 chunkpos.X * m_chunksize,
367 chunkpos.Y * m_chunksize
369 sectorpos.X -= m_chunksize / 2;
370 sectorpos.Y -= m_chunksize / 2;
377 MapChunk *getChunk(v2s16 chunkpos)
379 core::map<v2s16, MapChunk*>::Node *n;
380 n = m_chunks.find(chunkpos);
383 return n->getValue();
387 True if the chunk and its neighbors are fully generated.
388 It means the chunk will not be touched in the future by the
389 generator. If false, generateChunk will make it true.
391 bool chunkNonVolatile(v2s16 chunkpos)
396 /*for(s16 x=-1; x<=1; x++)
397 for(s16 y=-1; y<=1; y++)*/
401 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
402 MapChunk *chunk = getChunk(chunkpos);
405 if(chunk->getGenLevel() != GENERATED_FULLY)
412 Returns true if any chunk is marked as modified
414 bool anyChunkModified()
416 for(core::map<v2s16, MapChunk*>::Iterator
417 i = m_chunks.getIterator();
418 i.atEnd()==false; i++)
420 v2s16 p = i.getNode()->getKey();
421 MapChunk *chunk = i.getNode()->getValue();
422 if(chunk->isModified())
428 void setChunksNonModified()
430 for(core::map<v2s16, MapChunk*>::Iterator
431 i = m_chunks.getIterator();
432 i.atEnd()==false; i++)
434 v2s16 p = i.getNode()->getKey();
435 MapChunk *chunk = i.getNode()->getValue();
436 chunk->setModified(false);
441 Chunks are generated by using these and makeChunk().
443 void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
444 MapChunk* finishChunkMake(ChunkMakeData &data,
445 core::map<v3s16, MapBlock*> &changed_blocks);
450 All chunks touching this one can be altered also.
452 /*MapChunk* generateChunkRaw(v2s16 chunkpos,
453 core::map<v3s16, MapBlock*> &changed_blocks,
457 Generate a chunk and its neighbors so that it won't be touched
460 /*MapChunk* generateChunk(v2s16 chunkpos,
461 core::map<v3s16, MapBlock*> &changed_blocks);*/
466 This is mainly called by generateChunkRaw.
468 //ServerMapSector * generateSector(v2s16 p);
471 Get a sector from somewhere.
473 - Check disk (loads blocks also)
476 ServerMapSector * createSector(v2s16 p);
479 Get a sector from somewhere.
481 - Check disk (loads blocks also)
484 /*MapSector * emergeSector(v2s16 p,
485 core::map<v3s16, MapBlock*> &changed_blocks);*/
487 /*MapSector * emergeSector(v2s16 p)
489 core::map<v3s16, MapBlock*> changed_blocks;
490 return emergeSector(p, changed_blocks);
493 MapBlock * generateBlock(
495 MapBlock *original_dummy,
496 ServerMapSector *sector,
497 core::map<v3s16, MapBlock*> &changed_blocks,
498 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
502 Get a block from somewhere.
506 MapBlock * createBlock(v3s16 p);
509 only_from_disk, changed_blocks and lighting_invalidated_blocks
510 are not properly used by the new map generator.
512 MapBlock * emergeBlock(
515 core::map<v3s16, MapBlock*> &changed_blocks,
516 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
521 Forcefully get a block from somewhere.
524 - InvalidPositionException: possible if only_from_disk==true
527 - All already existing blocks that were modified are added.
528 - If found on disk, nothing will be added.
529 - If generated, the new block will not be included.
531 lighting_invalidated_blocks:
532 - All blocks that have heavy-to-calculate lighting changes
534 - updateLighting() should be called for these.
536 - A block that is in changed_blocks may not be in
537 lighting_invalidated_blocks.
539 MapBlock * emergeBlock(
542 core::map<v3s16, MapBlock*> &changed_blocks,
543 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
547 // Helper for placing objects on ground level
548 s16 findGroundLevel(v2s16 p2d);
551 Misc. helper functions for fiddling with directory and file
554 void createDirs(std::string path);
555 // returns something like "map/sectors/xxxxxxxx"
556 std::string getSectorDir(v2s16 pos, int layout = 2);
557 // dirname: final directory name
558 v2s16 getSectorPos(std::string dirname);
559 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
561 void save(bool only_changed);
564 // Saves map seed and possibly other stuff
568 void saveChunkMeta();
569 void loadChunkMeta();
571 // The sector mutex should be locked when calling most of these
573 // This only saves sector-specific data such as the heightmap
575 // DEPRECATED? Sectors have no metadata anymore.
576 void saveSectorMeta(ServerMapSector *sector);
577 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
579 // Full load of a sector including all blocks.
580 // returns true on success, false on failure.
581 bool loadSectorFull(v2s16 p2d);
582 // If sector is not found in memory, try to load it from disk.
583 // Returns true if sector now resides in memory
584 //bool deFlushSector(v2s16 p2d);
586 void saveBlock(MapBlock *block);
587 // This will generate a sector with getSector if not found.
588 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
590 // For debug printing
591 virtual void PrintInfo(std::ostream &out);
593 bool isSavingEnabled(){ return m_map_saving_enabled; }
596 // Seed used for all kinds of randomness
599 std::string m_savedir;
600 bool m_map_saving_enabled;
602 // Chunk size in MapSectors
603 // If 0, chunks are disabled.
606 core::map<v2s16, MapChunk*> m_chunks;
609 Metadata is re-written on disk only if this is true.
610 This is reset to false when written on disk.
612 bool m_map_metadata_changed;
621 struct MapDrawControl
626 wanted_max_blocks(0),
629 blocks_would_have_drawn(0)
632 // Overrides limits by drawing everything
634 // Wanted drawing range
636 // Maximum number of blocks to draw
637 u32 wanted_max_blocks;
638 // Blocks in this range are drawn regardless of number of blocks drawn
639 float wanted_min_range;
640 // Number of blocks rendered is written here by the renderer
642 // Number of blocks that would have been drawn in wanted_range
643 u32 blocks_would_have_drawn;
651 This is the only map class that is able to render itself on screen.
654 class ClientMap : public Map, public scene::ISceneNode
659 MapDrawControl &control,
660 scene::ISceneNode* parent,
661 scene::ISceneManager* mgr,
669 return MAPTYPE_CLIENT;
677 void updateCamera(v3f pos, v3f dir)
679 JMutexAutoLock lock(m_camera_mutex);
680 m_camera_position = pos;
681 m_camera_direction = dir;
685 Forcefully get a sector from somewhere
687 MapSector * emergeSector(v2s16 p);
689 void deSerializeSector(v2s16 p2d, std::istream &is);
695 virtual void OnRegisterSceneNode();
697 virtual void render()
699 video::IVideoDriver* driver = SceneManager->getVideoDriver();
700 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
701 renderMap(driver, SceneManager->getSceneNodeRenderPass());
704 virtual const core::aabbox3d<f32>& getBoundingBox() const
709 void renderMap(video::IVideoDriver* driver, s32 pass);
712 Methods for setting temporary modifications to nodes for
715 Returns true if something changed.
717 All blocks whose mesh could have been changed are inserted
720 bool setTempMod(v3s16 p, NodeMod mod,
721 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
722 bool clearTempMod(v3s16 p,
723 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
724 // Efficient implementation needs a cache of TempMods
725 //void clearTempMods();
727 void expireMeshes(bool only_daynight_diffed);
730 Update the faces of the given block and blocks on the
733 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
735 // Update meshes that touch the node
736 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
738 // For debug printing
739 virtual void PrintInfo(std::ostream &out);
744 core::aabbox3d<f32> m_box;
746 // This is the master heightmap mesh
747 //scene::SMesh *mesh;
750 MapDrawControl &m_control;
752 v3f m_camera_position;
753 v3f m_camera_direction;
754 JMutex m_camera_mutex;
760 class MapVoxelManipulator : public VoxelManipulator
763 MapVoxelManipulator(Map *map);
764 virtual ~MapVoxelManipulator();
768 VoxelManipulator::clear();
769 m_loaded_blocks.clear();
772 virtual void emerge(VoxelArea a, s32 caller_id=-1);
774 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
780 value = block existed when loaded
782 core::map<v3s16, bool> m_loaded_blocks;
785 class ManualMapVoxelManipulator : public MapVoxelManipulator
788 ManualMapVoxelManipulator(Map *map);
789 virtual ~ManualMapVoxelManipulator();
791 void setMap(Map *map)
794 virtual void emerge(VoxelArea a, s32 caller_id=-1);
796 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
798 // This is much faster with big chunks of generated data
799 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
808 ManualMapVoxelManipulator vmanip;
813 v2s16 sectorpos_base;
814 s16 sectorpos_base_size;
815 v2s16 sectorpos_bigbase;
816 s16 sectorpos_bigbase_size;
817 s16 max_spread_amount;
818 UniqueQueue<v3s16> transforming_liquid;
827 void makeChunk(ChunkMakeData *data);