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"
48 #define MAPTYPE_BASE 0
49 #define MAPTYPE_SERVER 1
50 #define MAPTYPE_CLIENT 2
52 enum MapEditEventType{
53 // Node added (changed from air or something else to something)
55 // Node removed (changed to air)
57 // Node metadata of block changed (not knowing which node exactly)
58 // p stores block coordinate
59 MEET_BLOCK_NODE_METADATA_CHANGED,
66 MapEditEventType type;
69 core::map<v3s16, bool> modified_blocks;
70 u16 already_known_by_peer;
74 already_known_by_peer(0)
78 MapEditEvent * clone()
80 MapEditEvent *event = new MapEditEvent();
84 for(core::map<v3s16, bool>::Iterator
85 i = modified_blocks.getIterator();
86 i.atEnd()==false; i++)
88 v3s16 p = i.getNode()->getKey();
89 bool v = i.getNode()->getValue();
90 event->modified_blocks.insert(p, v);
96 class MapEventReceiver
99 // event shall be deleted by caller after the call.
100 virtual void onMapEditEvent(MapEditEvent *event) = 0;
103 class Map : public NodeContainer
107 Map(std::ostream &dout);
110 virtual u16 nodeContainerId() const
112 return NODECONTAINER_ID_MAP;
115 virtual s32 mapType() const
121 Drop (client) or delete (server) the map.
128 void addEventReceiver(MapEventReceiver *event_receiver);
129 void removeEventReceiver(MapEventReceiver *event_receiver);
130 // event shall be deleted by caller after the call.
131 void dispatchEvent(MapEditEvent *event);
133 // On failure returns NULL
134 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
135 // On failure returns NULL
136 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
137 // On failure throws InvalidPositionException
138 MapSector * getSectorNoGenerate(v2s16 p2d);
139 // Gets an existing sector or creates an empty one
140 //MapSector * getSectorCreate(v2s16 p2d);
143 This is overloaded by ClientMap and ServerMap to allow
144 their differing fetch methods.
146 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
147 virtual MapSector * emergeSector(v2s16 p,
148 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
150 // Returns InvalidPositionException if not found
151 MapBlock * getBlockNoCreate(v3s16 p);
152 // Returns NULL if not found
153 MapBlock * getBlockNoCreateNoEx(v3s16 p);
154 // Gets an existing block or creates an empty one
155 //MapBlock * getBlockCreate(v3s16 p);
157 // Returns InvalidPositionException if not found
158 bool isNodeUnderground(v3s16 p);
160 // virtual from NodeContainer
161 bool isValidPosition(v3s16 p)
163 v3s16 blockpos = getNodeBlockPos(p);
166 blockref = getBlockNoCreate(blockpos);
168 catch(InvalidPositionException &e)
173 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
174 bool is_valid = blockref->isValidPosition(relpos);
178 // virtual from NodeContainer
179 // throws InvalidPositionException if not found
180 MapNode getNode(v3s16 p)
182 v3s16 blockpos = getNodeBlockPos(p);
183 MapBlock * blockref = getBlockNoCreate(blockpos);
184 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
186 return blockref->getNodeNoCheck(relpos);
189 // virtual from NodeContainer
190 // throws InvalidPositionException if not found
191 void setNode(v3s16 p, MapNode & n)
193 v3s16 blockpos = getNodeBlockPos(p);
194 MapBlock * blockref = getBlockNoCreate(blockpos);
195 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
196 blockref->setNodeNoCheck(relpos, n);
199 // Returns a CONTENT_IGNORE node if not found
200 MapNode getNodeNoEx(v3s16 p)
203 v3s16 blockpos = getNodeBlockPos(p);
204 MapBlock * blockref = getBlockNoCreate(blockpos);
205 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
207 return blockref->getNodeNoCheck(relpos);
209 catch(InvalidPositionException &e)
211 return MapNode(CONTENT_IGNORE);
215 void unspreadLight(enum LightBank bank,
216 core::map<v3s16, u8> & from_nodes,
217 core::map<v3s16, bool> & light_sources,
218 core::map<v3s16, MapBlock*> & modified_blocks);
220 void unLightNeighbors(enum LightBank bank,
221 v3s16 pos, u8 lightwas,
222 core::map<v3s16, bool> & light_sources,
223 core::map<v3s16, MapBlock*> & modified_blocks);
225 void spreadLight(enum LightBank bank,
226 core::map<v3s16, bool> & from_nodes,
227 core::map<v3s16, MapBlock*> & modified_blocks);
229 void lightNeighbors(enum LightBank bank,
231 core::map<v3s16, MapBlock*> & modified_blocks);
233 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
235 s16 propagateSunlight(v3s16 start,
236 core::map<v3s16, MapBlock*> & modified_blocks);
238 void updateLighting(enum LightBank bank,
239 core::map<v3s16, MapBlock*> & a_blocks,
240 core::map<v3s16, MapBlock*> & modified_blocks);
242 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
243 core::map<v3s16, MapBlock*> & modified_blocks);
246 These handle lighting but not faces.
248 void addNodeAndUpdate(v3s16 p, MapNode n,
249 core::map<v3s16, MapBlock*> &modified_blocks);
250 void removeNodeAndUpdate(v3s16 p,
251 core::map<v3s16, MapBlock*> &modified_blocks);
254 Wrappers for the latter ones.
256 Return true if succeeded, false if not.
258 bool addNodeWithEvent(v3s16 p, MapNode n);
259 bool removeNodeWithEvent(v3s16 p);
262 Takes the blocks at the edges into account
264 bool dayNightDiffed(v3s16 blockpos);
266 //core::aabbox3d<s16> getDisplayedBlockArea();
268 //bool updateChangedVisibleArea();
270 virtual void save(bool only_changed){assert(0);};
275 void timerUpdate(float dtime);
277 // Takes cache into account
278 // sector mutex should be locked when calling
279 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
281 // Returns count of deleted sectors
282 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
283 core::list<v3s16> *deleted_blocks=NULL);
285 // For debug printing
286 virtual void PrintInfo(std::ostream &out);
288 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
292 These are basically coordinate wrappers to MapBlock
295 NodeMetadata* getNodeMetadata(v3s16 p);
296 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
297 void removeNodeMetadata(v3s16 p);
298 void nodeMetadataStep(float dtime,
299 core::map<v3s16, MapBlock*> &changed_blocks);
304 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
312 std::ostream &m_dout;
314 core::map<MapEventReceiver*, bool> m_event_receivers;
316 core::map<v2s16, MapSector*> m_sectors;
317 //JMutex m_sector_mutex;
319 // Be sure to set this to NULL when the cached sector is deleted
320 MapSector *m_sector_cache;
321 v2s16 m_sector_cache_p;
323 // Queued transforming water nodes
324 UniqueQueue<v3s16> m_transforming_liquid;
330 This is the only map class that is able to generate map.
333 struct ChunkMakeData;
335 class ServerMap : public Map
339 savedir: directory to which map data should be saved
341 ServerMap(std::string savedir);
346 return MAPTYPE_SERVER;
353 // Returns the position of the chunk where the sector is in
354 v2s16 sector_to_chunk(v2s16 sectorpos)
358 sectorpos.X += m_chunksize / 2;
359 sectorpos.Y += m_chunksize / 2;
360 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
364 // Returns the position of the (0,0) sector of the chunk
365 v2s16 chunk_to_sector(v2s16 chunkpos)
370 chunkpos.X * m_chunksize,
371 chunkpos.Y * m_chunksize
373 sectorpos.X -= m_chunksize / 2;
374 sectorpos.Y -= m_chunksize / 2;
381 MapChunk *getChunk(v2s16 chunkpos)
383 core::map<v2s16, MapChunk*>::Node *n;
384 n = m_chunks.find(chunkpos);
387 return n->getValue();
391 True if the chunk and its neighbors are fully generated.
392 It means the chunk will not be touched in the future by the
393 generator. If false, generateChunk will make it true.
395 bool chunkNonVolatile(v2s16 chunkpos)
400 /*for(s16 x=-1; x<=1; x++)
401 for(s16 y=-1; y<=1; y++)*/
405 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
406 MapChunk *chunk = getChunk(chunkpos);
409 if(chunk->getGenLevel() != GENERATED_FULLY)
416 Returns true if any chunk is marked as modified
418 bool anyChunkModified()
420 for(core::map<v2s16, MapChunk*>::Iterator
421 i = m_chunks.getIterator();
422 i.atEnd()==false; i++)
424 v2s16 p = i.getNode()->getKey();
425 MapChunk *chunk = i.getNode()->getValue();
426 if(chunk->isModified())
432 void setChunksNonModified()
434 for(core::map<v2s16, MapChunk*>::Iterator
435 i = m_chunks.getIterator();
436 i.atEnd()==false; i++)
438 v2s16 p = i.getNode()->getKey();
439 MapChunk *chunk = i.getNode()->getValue();
440 chunk->setModified(false);
445 Chunks are generated by using these and makeChunk().
447 void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
448 MapChunk* finishChunkMake(ChunkMakeData &data,
449 core::map<v3s16, MapBlock*> &changed_blocks);
454 All chunks touching this one can be altered also.
456 /*MapChunk* generateChunkRaw(v2s16 chunkpos,
457 core::map<v3s16, MapBlock*> &changed_blocks,
461 Generate a chunk and its neighbors so that it won't be touched
464 /*MapChunk* generateChunk(v2s16 chunkpos,
465 core::map<v3s16, MapBlock*> &changed_blocks);*/
470 This is mainly called by generateChunkRaw.
472 //ServerMapSector * generateSector(v2s16 p);
475 Get a sector from somewhere.
477 - Check disk (loads blocks also)
480 ServerMapSector * createSector(v2s16 p);
483 Get a sector from somewhere.
485 - Check disk (loads blocks also)
488 /*MapSector * emergeSector(v2s16 p,
489 core::map<v3s16, MapBlock*> &changed_blocks);*/
491 /*MapSector * emergeSector(v2s16 p)
493 core::map<v3s16, MapBlock*> changed_blocks;
494 return emergeSector(p, changed_blocks);
497 MapBlock * generateBlock(
499 MapBlock *original_dummy,
500 ServerMapSector *sector,
501 core::map<v3s16, MapBlock*> &changed_blocks,
502 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
506 Get a block from somewhere.
510 MapBlock * createBlock(v3s16 p);
513 only_from_disk, changed_blocks and lighting_invalidated_blocks
514 are not properly used by the new map generator.
516 MapBlock * emergeBlock(
519 core::map<v3s16, MapBlock*> &changed_blocks,
520 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
525 Forcefully get a block from somewhere.
528 - InvalidPositionException: possible if only_from_disk==true
531 - All already existing blocks that were modified are added.
532 - If found on disk, nothing will be added.
533 - If generated, the new block will not be included.
535 lighting_invalidated_blocks:
536 - All blocks that have heavy-to-calculate lighting changes
538 - updateLighting() should be called for these.
540 - A block that is in changed_blocks may not be in
541 lighting_invalidated_blocks.
543 MapBlock * emergeBlock(
546 core::map<v3s16, MapBlock*> &changed_blocks,
547 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
551 // Helper for placing objects on ground level
552 s16 findGroundLevel(v2s16 p2d);
555 Misc. helper functions for fiddling with directory and file
558 void createDirs(std::string path);
559 // returns something like "map/sectors/xxxxxxxx"
560 std::string getSectorDir(v2s16 pos, int layout = 2);
561 // dirname: final directory name
562 v2s16 getSectorPos(std::string dirname);
563 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
565 void save(bool only_changed);
568 // Saves map seed and possibly other stuff
572 void saveChunkMeta();
573 void loadChunkMeta();
575 // The sector mutex should be locked when calling most of these
577 // This only saves sector-specific data such as the heightmap
579 // DEPRECATED? Sectors have no metadata anymore.
580 void saveSectorMeta(ServerMapSector *sector);
581 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
583 // Full load of a sector including all blocks.
584 // returns true on success, false on failure.
585 bool loadSectorFull(v2s16 p2d);
586 // If sector is not found in memory, try to load it from disk.
587 // Returns true if sector now resides in memory
588 //bool deFlushSector(v2s16 p2d);
590 void saveBlock(MapBlock *block);
591 // This will generate a sector with getSector if not found.
592 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
594 // For debug printing
595 virtual void PrintInfo(std::ostream &out);
597 bool isSavingEnabled(){ return m_map_saving_enabled; }
599 u64 getSeed(){ return m_seed; }
602 // Seed used for all kinds of randomness
605 std::string m_savedir;
606 bool m_map_saving_enabled;
608 // Chunk size in MapSectors
609 // If 0, chunks are disabled.
612 core::map<v2s16, MapChunk*> m_chunks;
615 Metadata is re-written on disk only if this is true.
616 This is reset to false when written on disk.
618 bool m_map_metadata_changed;
627 struct MapDrawControl
632 wanted_max_blocks(0),
635 blocks_would_have_drawn(0)
638 // Overrides limits by drawing everything
640 // Wanted drawing range
642 // Maximum number of blocks to draw
643 u32 wanted_max_blocks;
644 // Blocks in this range are drawn regardless of number of blocks drawn
645 float wanted_min_range;
646 // Number of blocks rendered is written here by the renderer
648 // Number of blocks that would have been drawn in wanted_range
649 u32 blocks_would_have_drawn;
657 This is the only map class that is able to render itself on screen.
660 class ClientMap : public Map, public scene::ISceneNode
665 MapDrawControl &control,
666 scene::ISceneNode* parent,
667 scene::ISceneManager* mgr,
675 return MAPTYPE_CLIENT;
683 void updateCamera(v3f pos, v3f dir)
685 JMutexAutoLock lock(m_camera_mutex);
686 m_camera_position = pos;
687 m_camera_direction = dir;
691 Forcefully get a sector from somewhere
693 MapSector * emergeSector(v2s16 p);
695 void deSerializeSector(v2s16 p2d, std::istream &is);
701 virtual void OnRegisterSceneNode();
703 virtual void render()
705 video::IVideoDriver* driver = SceneManager->getVideoDriver();
706 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
707 renderMap(driver, SceneManager->getSceneNodeRenderPass());
710 virtual const core::aabbox3d<f32>& getBoundingBox() const
715 void renderMap(video::IVideoDriver* driver, s32 pass);
718 Methods for setting temporary modifications to nodes for
721 Returns true if something changed.
723 All blocks whose mesh could have been changed are inserted
726 bool setTempMod(v3s16 p, NodeMod mod,
727 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
728 bool clearTempMod(v3s16 p,
729 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
730 // Efficient implementation needs a cache of TempMods
731 //void clearTempMods();
733 void expireMeshes(bool only_daynight_diffed);
736 Update the faces of the given block and blocks on the
739 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
741 // Update meshes that touch the node
742 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
744 // For debug printing
745 virtual void PrintInfo(std::ostream &out);
747 // Check if sector was drawn on last render()
748 bool sectorWasDrawn(v2s16 p)
750 return (m_last_drawn_sectors.find(p) != NULL);
756 core::aabbox3d<f32> m_box;
758 // This is the master heightmap mesh
759 //scene::SMesh *mesh;
762 MapDrawControl &m_control;
764 v3f m_camera_position;
765 v3f m_camera_direction;
766 JMutex m_camera_mutex;
768 core::map<v2s16, bool> m_last_drawn_sectors;
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);