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"
45 Temporarily exposed map generator stuff
46 Should only be used for testing
49 double base_rock_level_2d(u64 seed, v2s16 p);
55 #define MAPTYPE_BASE 0
56 #define MAPTYPE_SERVER 1
57 #define MAPTYPE_CLIENT 2
59 enum MapEditEventType{
60 // Node added (changed from air or something else to something)
62 // Node removed (changed to air)
64 // Node metadata of block changed (not knowing which node exactly)
65 // p stores block coordinate
66 MEET_BLOCK_NODE_METADATA_CHANGED,
73 MapEditEventType type;
76 core::map<v3s16, bool> modified_blocks;
77 u16 already_known_by_peer;
81 already_known_by_peer(0)
85 MapEditEvent * clone()
87 MapEditEvent *event = new MapEditEvent();
91 for(core::map<v3s16, bool>::Iterator
92 i = modified_blocks.getIterator();
93 i.atEnd()==false; i++)
95 v3s16 p = i.getNode()->getKey();
96 bool v = i.getNode()->getValue();
97 event->modified_blocks.insert(p, v);
103 class MapEventReceiver
106 // event shall be deleted by caller after the call.
107 virtual void onMapEditEvent(MapEditEvent *event) = 0;
110 class Map : public NodeContainer
114 Map(std::ostream &dout);
117 virtual u16 nodeContainerId() const
119 return NODECONTAINER_ID_MAP;
122 virtual s32 mapType() const
128 Drop (client) or delete (server) the map.
135 void addEventReceiver(MapEventReceiver *event_receiver);
136 void removeEventReceiver(MapEventReceiver *event_receiver);
137 // event shall be deleted by caller after the call.
138 void dispatchEvent(MapEditEvent *event);
140 // On failure returns NULL
141 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
142 // On failure returns NULL
143 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
144 // On failure throws InvalidPositionException
145 MapSector * getSectorNoGenerate(v2s16 p2d);
146 // Gets an existing sector or creates an empty one
147 //MapSector * getSectorCreate(v2s16 p2d);
150 This is overloaded by ClientMap and ServerMap to allow
151 their differing fetch methods.
153 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
154 virtual MapSector * emergeSector(v2s16 p,
155 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
157 // Returns InvalidPositionException if not found
158 MapBlock * getBlockNoCreate(v3s16 p);
159 // Returns NULL if not found
160 MapBlock * getBlockNoCreateNoEx(v3s16 p);
161 // Gets an existing block or creates an empty one
162 //MapBlock * getBlockCreate(v3s16 p);
164 // Returns InvalidPositionException if not found
165 bool isNodeUnderground(v3s16 p);
167 // virtual from NodeContainer
168 bool isValidPosition(v3s16 p)
170 v3s16 blockpos = getNodeBlockPos(p);
173 blockref = getBlockNoCreate(blockpos);
175 catch(InvalidPositionException &e)
180 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
181 bool is_valid = blockref->isValidPosition(relpos);
185 // virtual from NodeContainer
186 // throws InvalidPositionException if not found
187 MapNode getNode(v3s16 p)
189 v3s16 blockpos = getNodeBlockPos(p);
190 MapBlock * blockref = getBlockNoCreate(blockpos);
191 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
193 return blockref->getNodeNoCheck(relpos);
196 // virtual from NodeContainer
197 // throws InvalidPositionException if not found
198 void setNode(v3s16 p, MapNode & n)
200 v3s16 blockpos = getNodeBlockPos(p);
201 MapBlock * blockref = getBlockNoCreate(blockpos);
202 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
203 blockref->setNodeNoCheck(relpos, n);
206 // Returns a CONTENT_IGNORE node if not found
207 MapNode getNodeNoEx(v3s16 p)
210 v3s16 blockpos = getNodeBlockPos(p);
211 MapBlock * blockref = getBlockNoCreate(blockpos);
212 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
214 return blockref->getNodeNoCheck(relpos);
216 catch(InvalidPositionException &e)
218 return MapNode(CONTENT_IGNORE);
222 void unspreadLight(enum LightBank bank,
223 core::map<v3s16, u8> & from_nodes,
224 core::map<v3s16, bool> & light_sources,
225 core::map<v3s16, MapBlock*> & modified_blocks);
227 void unLightNeighbors(enum LightBank bank,
228 v3s16 pos, u8 lightwas,
229 core::map<v3s16, bool> & light_sources,
230 core::map<v3s16, MapBlock*> & modified_blocks);
232 void spreadLight(enum LightBank bank,
233 core::map<v3s16, bool> & from_nodes,
234 core::map<v3s16, MapBlock*> & modified_blocks);
236 void lightNeighbors(enum LightBank bank,
238 core::map<v3s16, MapBlock*> & modified_blocks);
240 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
242 s16 propagateSunlight(v3s16 start,
243 core::map<v3s16, MapBlock*> & modified_blocks);
245 void updateLighting(enum LightBank bank,
246 core::map<v3s16, MapBlock*> & a_blocks,
247 core::map<v3s16, MapBlock*> & modified_blocks);
249 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
250 core::map<v3s16, MapBlock*> & modified_blocks);
253 These handle lighting but not faces.
255 void addNodeAndUpdate(v3s16 p, MapNode n,
256 core::map<v3s16, MapBlock*> &modified_blocks);
257 void removeNodeAndUpdate(v3s16 p,
258 core::map<v3s16, MapBlock*> &modified_blocks);
261 Wrappers for the latter ones.
263 Return true if succeeded, false if not.
265 bool addNodeWithEvent(v3s16 p, MapNode n);
266 bool removeNodeWithEvent(v3s16 p);
269 Takes the blocks at the edges into account
271 bool dayNightDiffed(v3s16 blockpos);
273 //core::aabbox3d<s16> getDisplayedBlockArea();
275 //bool updateChangedVisibleArea();
277 virtual void save(bool only_changed){assert(0);};
282 void timerUpdate(float dtime);
284 // Takes cache into account
285 // sector mutex should be locked when calling
286 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
288 // Returns count of deleted sectors
289 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
290 core::list<v3s16> *deleted_blocks=NULL);
292 // For debug printing
293 virtual void PrintInfo(std::ostream &out);
295 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
299 These are basically coordinate wrappers to MapBlock
302 NodeMetadata* getNodeMetadata(v3s16 p);
303 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
304 void removeNodeMetadata(v3s16 p);
305 void nodeMetadataStep(float dtime,
306 core::map<v3s16, MapBlock*> &changed_blocks);
311 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
319 std::ostream &m_dout;
321 core::map<MapEventReceiver*, bool> m_event_receivers;
323 core::map<v2s16, MapSector*> m_sectors;
324 //JMutex m_sector_mutex;
326 // Be sure to set this to NULL when the cached sector is deleted
327 MapSector *m_sector_cache;
328 v2s16 m_sector_cache_p;
330 // Queued transforming water nodes
331 UniqueQueue<v3s16> m_transforming_liquid;
337 This is the only map class that is able to generate map.
340 struct ChunkMakeData;
342 class ServerMap : public Map
346 savedir: directory to which map data should be saved
348 ServerMap(std::string savedir);
353 return MAPTYPE_SERVER;
360 // Returns the position of the chunk where the sector is in
361 v2s16 sector_to_chunk(v2s16 sectorpos)
365 sectorpos.X += m_chunksize / 2;
366 sectorpos.Y += m_chunksize / 2;
367 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
371 // Returns the position of the (0,0) sector of the chunk
372 v2s16 chunk_to_sector(v2s16 chunkpos)
377 chunkpos.X * m_chunksize,
378 chunkpos.Y * m_chunksize
380 sectorpos.X -= m_chunksize / 2;
381 sectorpos.Y -= m_chunksize / 2;
388 MapChunk *getChunk(v2s16 chunkpos)
390 core::map<v2s16, MapChunk*>::Node *n;
391 n = m_chunks.find(chunkpos);
394 return n->getValue();
398 True if the chunk and its neighbors are fully generated.
399 It means the chunk will not be touched in the future by the
400 generator. If false, generateChunk will make it true.
402 bool chunkNonVolatile(v2s16 chunkpos)
407 /*for(s16 x=-1; x<=1; x++)
408 for(s16 y=-1; y<=1; y++)*/
412 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
413 MapChunk *chunk = getChunk(chunkpos);
416 if(chunk->getGenLevel() != GENERATED_FULLY)
423 Returns true if any chunk is marked as modified
425 bool anyChunkModified()
427 for(core::map<v2s16, MapChunk*>::Iterator
428 i = m_chunks.getIterator();
429 i.atEnd()==false; i++)
431 v2s16 p = i.getNode()->getKey();
432 MapChunk *chunk = i.getNode()->getValue();
433 if(chunk->isModified())
439 void setChunksNonModified()
441 for(core::map<v2s16, MapChunk*>::Iterator
442 i = m_chunks.getIterator();
443 i.atEnd()==false; i++)
445 v2s16 p = i.getNode()->getKey();
446 MapChunk *chunk = i.getNode()->getValue();
447 chunk->setModified(false);
452 Chunks are generated by using these and makeChunk().
454 void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
455 MapChunk* finishChunkMake(ChunkMakeData &data,
456 core::map<v3s16, MapBlock*> &changed_blocks);
461 All chunks touching this one can be altered also.
463 /*MapChunk* generateChunkRaw(v2s16 chunkpos,
464 core::map<v3s16, MapBlock*> &changed_blocks,
468 Generate a chunk and its neighbors so that it won't be touched
471 /*MapChunk* generateChunk(v2s16 chunkpos,
472 core::map<v3s16, MapBlock*> &changed_blocks);*/
477 This is mainly called by generateChunkRaw.
479 //ServerMapSector * generateSector(v2s16 p);
482 Get a sector from somewhere.
484 - Check disk (loads blocks also)
487 ServerMapSector * createSector(v2s16 p);
490 Get a sector from somewhere.
492 - Check disk (loads blocks also)
495 /*MapSector * emergeSector(v2s16 p,
496 core::map<v3s16, MapBlock*> &changed_blocks);*/
498 /*MapSector * emergeSector(v2s16 p)
500 core::map<v3s16, MapBlock*> changed_blocks;
501 return emergeSector(p, changed_blocks);
504 MapBlock * generateBlock(
506 MapBlock *original_dummy,
507 ServerMapSector *sector,
508 core::map<v3s16, MapBlock*> &changed_blocks,
509 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
513 Get a block from somewhere.
517 MapBlock * createBlock(v3s16 p);
520 only_from_disk, changed_blocks and lighting_invalidated_blocks
521 are not properly used by the new map generator.
523 MapBlock * emergeBlock(
526 core::map<v3s16, MapBlock*> &changed_blocks,
527 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
532 Forcefully get a block from somewhere.
535 - InvalidPositionException: possible if only_from_disk==true
538 - All already existing blocks that were modified are added.
539 - If found on disk, nothing will be added.
540 - If generated, the new block will not be included.
542 lighting_invalidated_blocks:
543 - All blocks that have heavy-to-calculate lighting changes
545 - updateLighting() should be called for these.
547 - A block that is in changed_blocks may not be in
548 lighting_invalidated_blocks.
550 MapBlock * emergeBlock(
553 core::map<v3s16, MapBlock*> &changed_blocks,
554 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
558 // Helper for placing objects on ground level
559 s16 findGroundLevel(v2s16 p2d);
562 Misc. helper functions for fiddling with directory and file
565 void createDirs(std::string path);
566 // returns something like "map/sectors/xxxxxxxx"
567 std::string getSectorDir(v2s16 pos, int layout = 2);
568 // dirname: final directory name
569 v2s16 getSectorPos(std::string dirname);
570 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
572 void save(bool only_changed);
575 // Saves map seed and possibly other stuff
579 void saveChunkMeta();
580 void loadChunkMeta();
582 // The sector mutex should be locked when calling most of these
584 // This only saves sector-specific data such as the heightmap
586 // DEPRECATED? Sectors have no metadata anymore.
587 void saveSectorMeta(ServerMapSector *sector);
588 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
590 // Full load of a sector including all blocks.
591 // returns true on success, false on failure.
592 bool loadSectorFull(v2s16 p2d);
593 // If sector is not found in memory, try to load it from disk.
594 // Returns true if sector now resides in memory
595 //bool deFlushSector(v2s16 p2d);
597 void saveBlock(MapBlock *block);
598 // This will generate a sector with getSector if not found.
599 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
601 // For debug printing
602 virtual void PrintInfo(std::ostream &out);
604 bool isSavingEnabled(){ return m_map_saving_enabled; }
606 u64 getSeed(){ return m_seed; }
609 // Seed used for all kinds of randomness
612 std::string m_savedir;
613 bool m_map_saving_enabled;
615 // Chunk size in MapSectors
616 // If 0, chunks are disabled.
619 core::map<v2s16, MapChunk*> m_chunks;
622 Metadata is re-written on disk only if this is true.
623 This is reset to false when written on disk.
625 bool m_map_metadata_changed;
634 struct MapDrawControl
639 wanted_max_blocks(0),
642 blocks_would_have_drawn(0)
645 // Overrides limits by drawing everything
647 // Wanted drawing range
649 // Maximum number of blocks to draw
650 u32 wanted_max_blocks;
651 // Blocks in this range are drawn regardless of number of blocks drawn
652 float wanted_min_range;
653 // Number of blocks rendered is written here by the renderer
655 // Number of blocks that would have been drawn in wanted_range
656 u32 blocks_would_have_drawn;
664 This is the only map class that is able to render itself on screen.
667 class ClientMap : public Map, public scene::ISceneNode
672 MapDrawControl &control,
673 scene::ISceneNode* parent,
674 scene::ISceneManager* mgr,
682 return MAPTYPE_CLIENT;
690 void updateCamera(v3f pos, v3f dir)
692 JMutexAutoLock lock(m_camera_mutex);
693 m_camera_position = pos;
694 m_camera_direction = dir;
698 Forcefully get a sector from somewhere
700 MapSector * emergeSector(v2s16 p);
702 void deSerializeSector(v2s16 p2d, std::istream &is);
708 virtual void OnRegisterSceneNode();
710 virtual void render()
712 video::IVideoDriver* driver = SceneManager->getVideoDriver();
713 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
714 renderMap(driver, SceneManager->getSceneNodeRenderPass());
717 virtual const core::aabbox3d<f32>& getBoundingBox() const
722 void renderMap(video::IVideoDriver* driver, s32 pass);
725 Methods for setting temporary modifications to nodes for
728 Returns true if something changed.
730 All blocks whose mesh could have been changed are inserted
733 bool setTempMod(v3s16 p, NodeMod mod,
734 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
735 bool clearTempMod(v3s16 p,
736 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
737 // Efficient implementation needs a cache of TempMods
738 //void clearTempMods();
740 void expireMeshes(bool only_daynight_diffed);
743 Update the faces of the given block and blocks on the
746 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
748 // Update meshes that touch the node
749 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
751 // For debug printing
752 virtual void PrintInfo(std::ostream &out);
757 core::aabbox3d<f32> m_box;
759 // This is the master heightmap mesh
760 //scene::SMesh *mesh;
763 MapDrawControl &m_control;
765 v3f m_camera_position;
766 v3f m_camera_direction;
767 JMutex m_camera_mutex;
773 class MapVoxelManipulator : public VoxelManipulator
776 MapVoxelManipulator(Map *map);
777 virtual ~MapVoxelManipulator();
781 VoxelManipulator::clear();
782 m_loaded_blocks.clear();
785 virtual void emerge(VoxelArea a, s32 caller_id=-1);
787 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
793 value = block existed when loaded
795 core::map<v3s16, bool> m_loaded_blocks;
798 class ManualMapVoxelManipulator : public MapVoxelManipulator
801 ManualMapVoxelManipulator(Map *map);
802 virtual ~ManualMapVoxelManipulator();
804 void setMap(Map *map)
807 virtual void emerge(VoxelArea a, s32 caller_id=-1);
809 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
811 // This is much faster with big chunks of generated data
812 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
821 ManualMapVoxelManipulator vmanip;
826 v2s16 sectorpos_base;
827 s16 sectorpos_base_size;
828 v2s16 sectorpos_bigbase;
829 s16 sectorpos_bigbase_size;
830 s16 max_spread_amount;
831 UniqueQueue<v3s16> transforming_liquid;
840 void makeChunk(ChunkMakeData *data);