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{
56 MapEditEventType type;
59 core::map<v3s16, bool> modified_blocks;
60 u16 already_known_by_peer;
64 already_known_by_peer(0)
68 MapEditEvent * clone()
70 MapEditEvent *event = new MapEditEvent();
74 for(core::map<v3s16, bool>::Iterator
75 i = modified_blocks.getIterator();
76 i.atEnd()==false; i++)
78 v3s16 p = i.getNode()->getKey();
79 bool v = i.getNode()->getValue();
80 event->modified_blocks.insert(p, v);
86 class MapEventReceiver
89 // event shall be deleted by caller after the call.
90 virtual void onMapEditEvent(MapEditEvent *event) = 0;
93 class Map : public NodeContainer
97 Map(std::ostream &dout);
100 virtual u16 nodeContainerId() const
102 return NODECONTAINER_ID_MAP;
105 virtual s32 mapType() const
111 Drop (client) or delete (server) the map.
118 void addEventReceiver(MapEventReceiver *event_receiver);
119 void removeEventReceiver(MapEventReceiver *event_receiver);
120 // event shall be deleted by caller after the call.
121 void dispatchEvent(MapEditEvent *event);
123 // On failure returns NULL
124 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
125 // On failure returns NULL
126 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
127 // On failure throws InvalidPositionException
128 MapSector * getSectorNoGenerate(v2s16 p2d);
129 // Gets an existing sector or creates an empty one
130 //MapSector * getSectorCreate(v2s16 p2d);
133 This is overloaded by ClientMap and ServerMap to allow
134 their differing fetch methods.
136 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
137 virtual MapSector * emergeSector(v2s16 p,
138 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
140 // Returns InvalidPositionException if not found
141 MapBlock * getBlockNoCreate(v3s16 p);
142 // Returns NULL if not found
143 MapBlock * getBlockNoCreateNoEx(v3s16 p);
144 // Gets an existing block or creates an empty one
145 //MapBlock * getBlockCreate(v3s16 p);
147 // Returns InvalidPositionException if not found
148 bool isNodeUnderground(v3s16 p);
150 // virtual from NodeContainer
151 bool isValidPosition(v3s16 p)
153 v3s16 blockpos = getNodeBlockPos(p);
156 blockref = getBlockNoCreate(blockpos);
158 catch(InvalidPositionException &e)
163 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
164 bool is_valid = blockref->isValidPosition(relpos);
168 // virtual from NodeContainer
169 // throws InvalidPositionException if not found
170 MapNode getNode(v3s16 p)
172 v3s16 blockpos = getNodeBlockPos(p);
173 MapBlock * blockref = getBlockNoCreate(blockpos);
174 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
176 return blockref->getNodeNoCheck(relpos);
179 // virtual from NodeContainer
180 // throws InvalidPositionException if not found
181 void setNode(v3s16 p, MapNode & n)
183 v3s16 blockpos = getNodeBlockPos(p);
184 MapBlock * blockref = getBlockNoCreate(blockpos);
185 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
186 blockref->setNodeNoCheck(relpos, n);
189 // Returns a CONTENT_IGNORE node if not found
190 MapNode getNodeNoEx(v3s16 p)
193 v3s16 blockpos = getNodeBlockPos(p);
194 MapBlock * blockref = getBlockNoCreate(blockpos);
195 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
197 return blockref->getNodeNoCheck(relpos);
199 catch(InvalidPositionException &e)
201 return MapNode(CONTENT_IGNORE);
205 void unspreadLight(enum LightBank bank,
206 core::map<v3s16, u8> & from_nodes,
207 core::map<v3s16, bool> & light_sources,
208 core::map<v3s16, MapBlock*> & modified_blocks);
210 void unLightNeighbors(enum LightBank bank,
211 v3s16 pos, u8 lightwas,
212 core::map<v3s16, bool> & light_sources,
213 core::map<v3s16, MapBlock*> & modified_blocks);
215 void spreadLight(enum LightBank bank,
216 core::map<v3s16, bool> & from_nodes,
217 core::map<v3s16, MapBlock*> & modified_blocks);
219 void lightNeighbors(enum LightBank bank,
221 core::map<v3s16, MapBlock*> & modified_blocks);
223 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
225 s16 propagateSunlight(v3s16 start,
226 core::map<v3s16, MapBlock*> & modified_blocks);
228 void updateLighting(enum LightBank bank,
229 core::map<v3s16, MapBlock*> & a_blocks,
230 core::map<v3s16, MapBlock*> & modified_blocks);
232 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
233 core::map<v3s16, MapBlock*> & modified_blocks);
236 These handle lighting but not faces.
238 void addNodeAndUpdate(v3s16 p, MapNode n,
239 core::map<v3s16, MapBlock*> &modified_blocks);
240 void removeNodeAndUpdate(v3s16 p,
241 core::map<v3s16, MapBlock*> &modified_blocks);
244 Wrappers for the latter ones.
246 Return true if succeeded, false if not.
248 bool addNodeWithEvent(v3s16 p, MapNode n);
249 bool removeNodeWithEvent(v3s16 p);
252 Takes the blocks at the edges into account
254 bool dayNightDiffed(v3s16 blockpos);
256 //core::aabbox3d<s16> getDisplayedBlockArea();
258 //bool updateChangedVisibleArea();
260 virtual void save(bool only_changed){assert(0);};
265 void timerUpdate(float dtime);
267 // Takes cache into account
268 // sector mutex should be locked when calling
269 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
271 // Returns count of deleted sectors
272 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
273 core::list<v3s16> *deleted_blocks=NULL);
275 // For debug printing
276 virtual void PrintInfo(std::ostream &out);
278 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
282 These are basically coordinate wrappers to MapBlock
285 NodeMetadata* getNodeMetadata(v3s16 p);
286 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
287 void removeNodeMetadata(v3s16 p);
288 void nodeMetadataStep(float dtime,
289 core::map<v3s16, MapBlock*> &changed_blocks);
294 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
302 std::ostream &m_dout;
304 core::map<MapEventReceiver*, bool> m_event_receivers;
306 core::map<v2s16, MapSector*> m_sectors;
307 //JMutex m_sector_mutex;
309 // Be sure to set this to NULL when the cached sector is deleted
310 MapSector *m_sector_cache;
311 v2s16 m_sector_cache_p;
313 // Queued transforming water nodes
314 UniqueQueue<v3s16> m_transforming_liquid;
320 This is the only map class that is able to generate map.
323 struct ChunkMakeData;
325 class ServerMap : public Map
329 savedir: directory to which map data should be saved
331 ServerMap(std::string savedir);
336 return MAPTYPE_SERVER;
343 // Returns the position of the chunk where the sector is in
344 v2s16 sector_to_chunk(v2s16 sectorpos)
348 sectorpos.X += m_chunksize / 2;
349 sectorpos.Y += m_chunksize / 2;
350 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
354 // Returns the position of the (0,0) sector of the chunk
355 v2s16 chunk_to_sector(v2s16 chunkpos)
360 chunkpos.X * m_chunksize,
361 chunkpos.Y * m_chunksize
363 sectorpos.X -= m_chunksize / 2;
364 sectorpos.Y -= m_chunksize / 2;
371 MapChunk *getChunk(v2s16 chunkpos)
373 core::map<v2s16, MapChunk*>::Node *n;
374 n = m_chunks.find(chunkpos);
377 return n->getValue();
381 True if the chunk and its neighbors are fully generated.
382 It means the chunk will not be touched in the future by the
383 generator. If false, generateChunk will make it true.
385 bool chunkNonVolatile(v2s16 chunkpos)
390 /*for(s16 x=-1; x<=1; x++)
391 for(s16 y=-1; y<=1; y++)*/
395 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
396 MapChunk *chunk = getChunk(chunkpos);
399 if(chunk->getGenLevel() != GENERATED_FULLY)
406 Returns true if any chunk is marked as modified
408 bool anyChunkModified()
410 for(core::map<v2s16, MapChunk*>::Iterator
411 i = m_chunks.getIterator();
412 i.atEnd()==false; i++)
414 v2s16 p = i.getNode()->getKey();
415 MapChunk *chunk = i.getNode()->getValue();
416 if(chunk->isModified())
422 void setChunksNonModified()
424 for(core::map<v2s16, MapChunk*>::Iterator
425 i = m_chunks.getIterator();
426 i.atEnd()==false; i++)
428 v2s16 p = i.getNode()->getKey();
429 MapChunk *chunk = i.getNode()->getValue();
430 chunk->setModified(false);
435 Chunks are generated by using these and makeChunk().
437 void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
438 MapChunk* finishChunkMake(ChunkMakeData &data,
439 core::map<v3s16, MapBlock*> &changed_blocks);
444 All chunks touching this one can be altered also.
446 /*MapChunk* generateChunkRaw(v2s16 chunkpos,
447 core::map<v3s16, MapBlock*> &changed_blocks,
451 Generate a chunk and its neighbors so that it won't be touched
454 /*MapChunk* generateChunk(v2s16 chunkpos,
455 core::map<v3s16, MapBlock*> &changed_blocks);*/
460 This is mainly called by generateChunkRaw.
462 //ServerMapSector * generateSector(v2s16 p);
465 Get a sector from somewhere.
467 - Check disk (loads blocks also)
470 ServerMapSector * createSector(v2s16 p);
473 Get a sector from somewhere.
475 - Check disk (loads blocks also)
478 /*MapSector * emergeSector(v2s16 p,
479 core::map<v3s16, MapBlock*> &changed_blocks);*/
481 /*MapSector * emergeSector(v2s16 p)
483 core::map<v3s16, MapBlock*> changed_blocks;
484 return emergeSector(p, changed_blocks);
487 MapBlock * generateBlock(
489 MapBlock *original_dummy,
490 ServerMapSector *sector,
491 core::map<v3s16, MapBlock*> &changed_blocks,
492 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
496 Get a block from somewhere.
500 MapBlock * createBlock(v3s16 p);
503 only_from_disk, changed_blocks and lighting_invalidated_blocks
504 are not properly used by the new map generator.
506 MapBlock * emergeBlock(
509 core::map<v3s16, MapBlock*> &changed_blocks,
510 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
515 Forcefully get a block from somewhere.
518 - InvalidPositionException: possible if only_from_disk==true
521 - All already existing blocks that were modified are added.
522 - If found on disk, nothing will be added.
523 - If generated, the new block will not be included.
525 lighting_invalidated_blocks:
526 - All blocks that have heavy-to-calculate lighting changes
528 - updateLighting() should be called for these.
530 - A block that is in changed_blocks may not be in
531 lighting_invalidated_blocks.
533 MapBlock * emergeBlock(
536 core::map<v3s16, MapBlock*> &changed_blocks,
537 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
541 // Helper for placing objects on ground level
542 s16 findGroundLevel(v2s16 p2d);
545 Misc. helper functions for fiddling with directory and file
548 void createDirs(std::string path);
549 // returns something like "map/sectors/xxxxxxxx"
550 std::string getSectorDir(v2s16 pos, int layout = 2);
551 // dirname: final directory name
552 v2s16 getSectorPos(std::string dirname);
553 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
555 void save(bool only_changed);
558 // Saves map seed and possibly other stuff
562 void saveChunkMeta();
563 void loadChunkMeta();
565 // The sector mutex should be locked when calling most of these
567 // This only saves sector-specific data such as the heightmap
569 // DEPRECATED? Sectors have no metadata anymore.
570 void saveSectorMeta(ServerMapSector *sector);
571 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
573 // Full load of a sector including all blocks.
574 // returns true on success, false on failure.
575 bool loadSectorFull(v2s16 p2d);
576 // If sector is not found in memory, try to load it from disk.
577 // Returns true if sector now resides in memory
578 //bool deFlushSector(v2s16 p2d);
580 void saveBlock(MapBlock *block);
581 // This will generate a sector with getSector if not found.
582 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
584 // For debug printing
585 virtual void PrintInfo(std::ostream &out);
587 bool isSavingEnabled(){ return m_map_saving_enabled; }
590 // Seed used for all kinds of randomness
593 std::string m_savedir;
594 bool m_map_saving_enabled;
596 // Chunk size in MapSectors
597 // If 0, chunks are disabled.
600 core::map<v2s16, MapChunk*> m_chunks;
603 Metadata is re-written on disk only if this is true.
604 This is reset to false when written on disk.
606 bool m_map_metadata_changed;
615 struct MapDrawControl
620 wanted_max_blocks(0),
623 blocks_would_have_drawn(0)
626 // Overrides limits by drawing everything
628 // Wanted drawing range
630 // Maximum number of blocks to draw
631 u32 wanted_max_blocks;
632 // Blocks in this range are drawn regardless of number of blocks drawn
633 float wanted_min_range;
634 // Number of blocks rendered is written here by the renderer
636 // Number of blocks that would have been drawn in wanted_range
637 u32 blocks_would_have_drawn;
645 This is the only map class that is able to render itself on screen.
648 class ClientMap : public Map, public scene::ISceneNode
653 MapDrawControl &control,
654 scene::ISceneNode* parent,
655 scene::ISceneManager* mgr,
663 return MAPTYPE_CLIENT;
671 void updateCamera(v3f pos, v3f dir)
673 JMutexAutoLock lock(m_camera_mutex);
674 m_camera_position = pos;
675 m_camera_direction = dir;
679 Forcefully get a sector from somewhere
681 MapSector * emergeSector(v2s16 p);
683 void deSerializeSector(v2s16 p2d, std::istream &is);
689 virtual void OnRegisterSceneNode();
691 virtual void render()
693 video::IVideoDriver* driver = SceneManager->getVideoDriver();
694 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
695 renderMap(driver, SceneManager->getSceneNodeRenderPass());
698 virtual const core::aabbox3d<f32>& getBoundingBox() const
703 void renderMap(video::IVideoDriver* driver, s32 pass);
706 Methods for setting temporary modifications to nodes for
709 Returns true if something changed.
711 All blocks whose mesh could have been changed are inserted
714 bool setTempMod(v3s16 p, NodeMod mod,
715 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
716 bool clearTempMod(v3s16 p,
717 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
718 // Efficient implementation needs a cache of TempMods
719 //void clearTempMods();
721 void expireMeshes(bool only_daynight_diffed);
724 Update the faces of the given block and blocks on the
727 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
729 // Update meshes that touch the node
730 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
732 // For debug printing
733 virtual void PrintInfo(std::ostream &out);
738 core::aabbox3d<f32> m_box;
740 // This is the master heightmap mesh
741 //scene::SMesh *mesh;
744 MapDrawControl &m_control;
746 v3f m_camera_position;
747 v3f m_camera_direction;
748 JMutex m_camera_mutex;
754 class MapVoxelManipulator : public VoxelManipulator
757 MapVoxelManipulator(Map *map);
758 virtual ~MapVoxelManipulator();
762 VoxelManipulator::clear();
763 m_loaded_blocks.clear();
766 virtual void emerge(VoxelArea a, s32 caller_id=-1);
768 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
774 value = block existed when loaded
776 core::map<v3s16, bool> m_loaded_blocks;
779 class ManualMapVoxelManipulator : public MapVoxelManipulator
782 ManualMapVoxelManipulator(Map *map);
783 virtual ~ManualMapVoxelManipulator();
785 void setMap(Map *map)
788 virtual void emerge(VoxelArea a, s32 caller_id=-1);
790 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
792 // This is much faster with big chunks of generated data
793 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
802 ManualMapVoxelManipulator vmanip;
807 v2s16 sectorpos_base;
808 s16 sectorpos_base_size;
809 v2s16 sectorpos_bigbase;
810 s16 sectorpos_bigbase_size;
811 s16 max_spread_amount;
812 UniqueQueue<v3s16> transforming_liquid;
821 void makeChunk(ChunkMakeData *data);