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 // Same as the above (there exists no lock anymore)
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);};
272 // Server implements this
273 virtual void saveBlock(MapBlock *block){};
278 void timerUpdate(float dtime);
280 // Takes cache into account
281 // sector mutex should be locked when calling
282 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
284 // Returns count of deleted sectors
285 u32 unloadUnusedData(float timeout, bool only_blocks=false,
286 core::list<v3s16> *deleted_blocks=NULL);
288 // For debug printing
289 virtual void PrintInfo(std::ostream &out);
291 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
295 These are basically coordinate wrappers to MapBlock
298 NodeMetadata* getNodeMetadata(v3s16 p);
299 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
300 void removeNodeMetadata(v3s16 p);
301 void nodeMetadataStep(float dtime,
302 core::map<v3s16, MapBlock*> &changed_blocks);
307 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
315 std::ostream &m_dout;
317 core::map<MapEventReceiver*, bool> m_event_receivers;
319 core::map<v2s16, MapSector*> m_sectors;
320 //JMutex m_sector_mutex;
322 // Be sure to set this to NULL when the cached sector is deleted
323 MapSector *m_sector_cache;
324 v2s16 m_sector_cache_p;
326 // Queued transforming water nodes
327 UniqueQueue<v3s16> m_transforming_liquid;
333 This is the only map class that is able to generate map.
336 //struct ChunkMakeData;
338 struct BlockMakeData;
340 class ServerMap : public Map
344 savedir: directory to which map data should be saved
346 ServerMap(std::string savedir);
351 return MAPTYPE_SERVER;
355 Get a sector from somewhere.
357 - Check disk (doesn't load blocks)
360 ServerMapSector * createSector(v2s16 p);
363 Blocks are generated by using these and makeBlock().
365 void initBlockMake(BlockMakeData *data, v3s16 blockpos);
366 MapBlock* finishBlockMake(BlockMakeData *data,
367 core::map<v3s16, MapBlock*> &changed_blocks);
369 // A non-threaded wrapper to the above
370 MapBlock * generateBlock(
372 core::map<v3s16, MapBlock*> &modified_blocks
376 Get a block from somewhere.
380 MapBlock * createBlock(v3s16 p);
384 NOTE: This comment might be outdated
386 Forcefully get a block from somewhere.
388 InvalidPositionException possible if only_from_disk==true
391 changed_blocks: Blocks that have been modified
393 MapBlock * emergeBlock(
396 core::map<v3s16, MapBlock*> &changed_blocks,
397 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
401 // Helper for placing objects on ground level
402 s16 findGroundLevel(v2s16 p2d);
405 Misc. helper functions for fiddling with directory and file
408 void createDirs(std::string path);
409 // returns something like "map/sectors/xxxxxxxx"
410 std::string getSectorDir(v2s16 pos, int layout = 2);
411 // dirname: final directory name
412 v2s16 getSectorPos(std::string dirname);
413 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
414 static std::string getBlockFilename(v3s16 p);
416 void save(bool only_changed);
419 // Saves map seed and possibly other stuff
423 /*void saveChunkMeta();
424 void loadChunkMeta();*/
426 // The sector mutex should be locked when calling most of these
428 // This only saves sector-specific data such as the heightmap
430 // DEPRECATED? Sectors have no metadata anymore.
431 void saveSectorMeta(ServerMapSector *sector);
432 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
433 bool loadSectorMeta(v2s16 p2d);
435 // Full load of a sector including all blocks.
436 // returns true on success, false on failure.
437 bool loadSectorFull(v2s16 p2d);
438 // If sector is not found in memory, try to load it from disk.
439 // Returns true if sector now resides in memory
440 //bool deFlushSector(v2s16 p2d);
442 void saveBlock(MapBlock *block);
443 // This will generate a sector with getSector if not found.
444 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
445 MapBlock* loadBlock(v3s16 p);
447 // For debug printing
448 virtual void PrintInfo(std::ostream &out);
450 bool isSavingEnabled(){ return m_map_saving_enabled; }
452 u64 getSeed(){ return m_seed; }
455 // Seed used for all kinds of randomness
458 std::string m_savedir;
459 bool m_map_saving_enabled;
462 // Chunk size in MapSectors
463 // If 0, chunks are disabled.
466 core::map<v2s16, MapChunk*> m_chunks;
470 Metadata is re-written on disk only if this is true.
471 This is reset to false when written on disk.
473 bool m_map_metadata_changed;
482 struct MapDrawControl
487 wanted_max_blocks(0),
490 blocks_would_have_drawn(0)
493 // Overrides limits by drawing everything
495 // Wanted drawing range
497 // Maximum number of blocks to draw
498 u32 wanted_max_blocks;
499 // Blocks in this range are drawn regardless of number of blocks drawn
500 float wanted_min_range;
501 // Number of blocks rendered is written here by the renderer
503 // Number of blocks that would have been drawn in wanted_range
504 u32 blocks_would_have_drawn;
512 This is the only map class that is able to render itself on screen.
515 class ClientMap : public Map, public scene::ISceneNode
520 MapDrawControl &control,
521 scene::ISceneNode* parent,
522 scene::ISceneManager* mgr,
530 return MAPTYPE_CLIENT;
538 void updateCamera(v3f pos, v3f dir)
540 JMutexAutoLock lock(m_camera_mutex);
541 m_camera_position = pos;
542 m_camera_direction = dir;
546 Forcefully get a sector from somewhere
548 MapSector * emergeSector(v2s16 p);
550 void deSerializeSector(v2s16 p2d, std::istream &is);
556 virtual void OnRegisterSceneNode();
558 virtual void render()
560 video::IVideoDriver* driver = SceneManager->getVideoDriver();
561 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
562 renderMap(driver, SceneManager->getSceneNodeRenderPass());
565 virtual const core::aabbox3d<f32>& getBoundingBox() const
570 void renderMap(video::IVideoDriver* driver, s32 pass);
573 Methods for setting temporary modifications to nodes for
576 Returns true if something changed.
578 All blocks whose mesh could have been changed are inserted
581 bool setTempMod(v3s16 p, NodeMod mod,
582 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
583 bool clearTempMod(v3s16 p,
584 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
585 // Efficient implementation needs a cache of TempMods
586 //void clearTempMods();
588 void expireMeshes(bool only_daynight_diffed);
591 Update the faces of the given block and blocks on the
594 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
596 // Update meshes that touch the node
597 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
599 // For debug printing
600 virtual void PrintInfo(std::ostream &out);
602 // Check if sector was drawn on last render()
603 bool sectorWasDrawn(v2s16 p)
605 return (m_last_drawn_sectors.find(p) != NULL);
611 core::aabbox3d<f32> m_box;
613 // This is the master heightmap mesh
614 //scene::SMesh *mesh;
617 MapDrawControl &m_control;
619 v3f m_camera_position;
620 v3f m_camera_direction;
621 JMutex m_camera_mutex;
623 core::map<v2s16, bool> m_last_drawn_sectors;
628 class MapVoxelManipulator : public VoxelManipulator
631 MapVoxelManipulator(Map *map);
632 virtual ~MapVoxelManipulator();
636 VoxelManipulator::clear();
637 m_loaded_blocks.clear();
640 virtual void emerge(VoxelArea a, s32 caller_id=-1);
642 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
648 value = block existed when loaded
650 core::map<v3s16, bool> m_loaded_blocks;
653 class ManualMapVoxelManipulator : public MapVoxelManipulator
656 ManualMapVoxelManipulator(Map *map);
657 virtual ~ManualMapVoxelManipulator();
659 void setMap(Map *map)
662 virtual void emerge(VoxelArea a, s32 caller_id=-1);
664 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
666 // This is much faster with big chunks of generated data
667 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
677 ManualMapVoxelManipulator vmanip;
682 v2s16 sectorpos_base;
683 s16 sectorpos_base_size;
684 v2s16 sectorpos_bigbase;
685 s16 sectorpos_bigbase_size;
686 s16 max_spread_amount;
687 UniqueQueue<v3s16> transforming_liquid;
696 void makeChunk(ChunkMakeData *data);
702 ManualMapVoxelManipulator vmanip;
705 UniqueQueue<v3s16> transforming_liquid;
714 void makeBlock(BlockMakeData *data);