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.
24 #include <jmutexautolock.h>
30 #define sleep_s(x) Sleep((x*1000))
33 #define sleep_s(x) sleep(x)
36 #include "common_irrlicht.h"
39 #include "constants.h"
42 #include "nodemetadata.h"
45 class ServerMapSector;
46 class ClientMapSector;
58 #define MAPTYPE_BASE 0
59 #define MAPTYPE_SERVER 1
60 #define MAPTYPE_CLIENT 2
62 enum MapEditEventType{
63 // Node added (changed from air or something else to something)
65 // Node removed (changed to air)
67 // Node metadata of block changed (not knowing which node exactly)
68 // p stores block coordinate
69 MEET_BLOCK_NODE_METADATA_CHANGED,
76 MapEditEventType type;
79 core::map<v3s16, bool> modified_blocks;
80 u16 already_known_by_peer;
84 already_known_by_peer(0)
88 MapEditEvent * clone()
90 MapEditEvent *event = new MapEditEvent();
94 for(core::map<v3s16, bool>::Iterator
95 i = modified_blocks.getIterator();
96 i.atEnd()==false; i++)
98 v3s16 p = i.getNode()->getKey();
99 bool v = i.getNode()->getValue();
100 event->modified_blocks.insert(p, v);
106 class MapEventReceiver
109 // event shall be deleted by caller after the call.
110 virtual void onMapEditEvent(MapEditEvent *event) = 0;
113 class Map /*: public NodeContainer*/
117 Map(std::ostream &dout);
120 /*virtual u16 nodeContainerId() const
122 return NODECONTAINER_ID_MAP;
125 virtual s32 mapType() const
131 Drop (client) or delete (server) the map.
138 void addEventReceiver(MapEventReceiver *event_receiver);
139 void removeEventReceiver(MapEventReceiver *event_receiver);
140 // event shall be deleted by caller after the call.
141 void dispatchEvent(MapEditEvent *event);
143 // On failure returns NULL
144 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
145 // Same as the above (there exists no lock anymore)
146 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
147 // On failure throws InvalidPositionException
148 MapSector * getSectorNoGenerate(v2s16 p2d);
149 // Gets an existing sector or creates an empty one
150 //MapSector * getSectorCreate(v2s16 p2d);
153 This is overloaded by ClientMap and ServerMap to allow
154 their differing fetch methods.
156 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
157 virtual MapSector * emergeSector(v2s16 p,
158 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
160 // Returns InvalidPositionException if not found
161 MapBlock * getBlockNoCreate(v3s16 p);
162 // Returns NULL if not found
163 MapBlock * getBlockNoCreateNoEx(v3s16 p);
164 // Gets an existing block or creates an empty one
165 //MapBlock * getBlockCreate(v3s16 p);
167 // Returns InvalidPositionException if not found
168 bool isNodeUnderground(v3s16 p);
170 // virtual from NodeContainer
171 bool isValidPosition(v3s16 p)
173 v3s16 blockpos = getNodeBlockPos(p);
176 blockref = getBlockNoCreate(blockpos);
178 catch(InvalidPositionException &e)
183 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
184 bool is_valid = blockref->isValidPosition(relpos);
188 // virtual from NodeContainer
189 // throws InvalidPositionException if not found
190 MapNode getNode(v3s16 p)
192 v3s16 blockpos = getNodeBlockPos(p);
193 MapBlock * blockref = getBlockNoCreate(blockpos);
194 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
196 return blockref->getNodeNoCheck(relpos);
199 // virtual from NodeContainer
200 // throws InvalidPositionException if not found
201 void setNode(v3s16 p, MapNode & n)
203 v3s16 blockpos = getNodeBlockPos(p);
204 MapBlock * blockref = getBlockNoCreate(blockpos);
205 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
206 blockref->setNodeNoCheck(relpos, n);
209 // Returns a CONTENT_IGNORE node if not found
210 MapNode getNodeNoEx(v3s16 p)
213 v3s16 blockpos = getNodeBlockPos(p);
214 MapBlock * blockref = getBlockNoCreate(blockpos);
215 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
217 return blockref->getNodeNoCheck(relpos);
219 catch(InvalidPositionException &e)
221 return MapNode(CONTENT_IGNORE);
225 void unspreadLight(enum LightBank bank,
226 core::map<v3s16, u8> & from_nodes,
227 core::map<v3s16, bool> & light_sources,
228 core::map<v3s16, MapBlock*> & modified_blocks);
230 void unLightNeighbors(enum LightBank bank,
231 v3s16 pos, u8 lightwas,
232 core::map<v3s16, bool> & light_sources,
233 core::map<v3s16, MapBlock*> & modified_blocks);
235 void spreadLight(enum LightBank bank,
236 core::map<v3s16, bool> & from_nodes,
237 core::map<v3s16, MapBlock*> & modified_blocks);
239 void lightNeighbors(enum LightBank bank,
241 core::map<v3s16, MapBlock*> & modified_blocks);
243 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
245 s16 propagateSunlight(v3s16 start,
246 core::map<v3s16, MapBlock*> & modified_blocks);
248 void updateLighting(enum LightBank bank,
249 core::map<v3s16, MapBlock*> & a_blocks,
250 core::map<v3s16, MapBlock*> & modified_blocks);
252 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
253 core::map<v3s16, MapBlock*> & modified_blocks);
256 These handle lighting but not faces.
258 void addNodeAndUpdate(v3s16 p, MapNode n,
259 core::map<v3s16, MapBlock*> &modified_blocks);
260 void removeNodeAndUpdate(v3s16 p,
261 core::map<v3s16, MapBlock*> &modified_blocks);
264 Wrappers for the latter ones.
266 Return true if succeeded, false if not.
268 bool addNodeWithEvent(v3s16 p, MapNode n);
269 bool removeNodeWithEvent(v3s16 p);
272 Takes the blocks at the edges into account
274 bool dayNightDiffed(v3s16 blockpos);
276 //core::aabbox3d<s16> getDisplayedBlockArea();
278 //bool updateChangedVisibleArea();
280 virtual void save(bool only_changed){assert(0);};
282 // Server implements this
283 virtual void saveBlock(MapBlock *block){};
288 void timerUpdate(float dtime);
290 // Takes cache into account
291 // sector mutex should be locked when calling
292 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
294 // Returns count of deleted sectors
295 u32 unloadUnusedData(float timeout, bool only_blocks=false,
296 core::list<v3s16> *deleted_blocks=NULL);
298 // For debug printing
299 virtual void PrintInfo(std::ostream &out);
301 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
305 These are basically coordinate wrappers to MapBlock
308 NodeMetadata* getNodeMetadata(v3s16 p);
309 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
310 void removeNodeMetadata(v3s16 p);
311 void nodeMetadataStep(float dtime,
312 core::map<v3s16, MapBlock*> &changed_blocks);
317 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
325 std::ostream &m_dout;
327 core::map<MapEventReceiver*, bool> m_event_receivers;
329 core::map<v2s16, MapSector*> m_sectors;
331 // Be sure to set this to NULL when the cached sector is deleted
332 MapSector *m_sector_cache;
333 v2s16 m_sector_cache_p;
335 // Queued transforming water nodes
336 UniqueQueue<v3s16> m_transforming_liquid;
342 This is the only map class that is able to generate map.
345 class ServerMap : public Map
349 savedir: directory to which map data should be saved
351 ServerMap(std::string savedir);
356 return MAPTYPE_SERVER;
360 Get a sector from somewhere.
362 - Check disk (doesn't load blocks)
365 ServerMapSector * createSector(v2s16 p);
368 Blocks are generated by using these and makeBlock().
370 void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
371 MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
372 core::map<v3s16, MapBlock*> &changed_blocks);
374 // A non-threaded wrapper to the above
375 MapBlock * generateBlock(
377 core::map<v3s16, MapBlock*> &modified_blocks
381 Get a block from somewhere.
385 MapBlock * createBlock(v3s16 p);
389 NOTE: This comment might be outdated
391 Forcefully get a block from somewhere.
393 InvalidPositionException possible if only_from_disk==true
396 changed_blocks: Blocks that have been modified
398 MapBlock * emergeBlock(
401 core::map<v3s16, MapBlock*> &changed_blocks,
402 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
406 // Helper for placing objects on ground level
407 s16 findGroundLevel(v2s16 p2d);
410 Misc. helper functions for fiddling with directory and file
413 void createDirs(std::string path);
414 // returns something like "map/sectors/xxxxxxxx"
415 std::string getSectorDir(v2s16 pos, int layout = 2);
416 // dirname: final directory name
417 v2s16 getSectorPos(std::string dirname);
418 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
419 static std::string getBlockFilename(v3s16 p);
421 void save(bool only_changed);
424 // Saves map seed and possibly other stuff
428 /*void saveChunkMeta();
429 void loadChunkMeta();*/
431 // The sector mutex should be locked when calling most of these
433 // This only saves sector-specific data such as the heightmap
435 // DEPRECATED? Sectors have no metadata anymore.
436 void saveSectorMeta(ServerMapSector *sector);
437 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
438 bool loadSectorMeta(v2s16 p2d);
440 // Full load of a sector including all blocks.
441 // returns true on success, false on failure.
442 bool loadSectorFull(v2s16 p2d);
443 // If sector is not found in memory, try to load it from disk.
444 // Returns true if sector now resides in memory
445 //bool deFlushSector(v2s16 p2d);
447 void saveBlock(MapBlock *block);
448 // This will generate a sector with getSector if not found.
449 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
450 MapBlock* loadBlock(v3s16 p);
452 // For debug printing
453 virtual void PrintInfo(std::ostream &out);
455 bool isSavingEnabled(){ return m_map_saving_enabled; }
457 u64 getSeed(){ return m_seed; }
460 // Seed used for all kinds of randomness
463 std::string m_savedir;
464 bool m_map_saving_enabled;
467 // Chunk size in MapSectors
468 // If 0, chunks are disabled.
471 core::map<v2s16, MapChunk*> m_chunks;
475 Metadata is re-written on disk only if this is true.
476 This is reset to false when written on disk.
478 bool m_map_metadata_changed;
487 struct MapDrawControl
492 wanted_max_blocks(0),
495 blocks_would_have_drawn(0)
498 // Overrides limits by drawing everything
500 // Wanted drawing range
502 // Maximum number of blocks to draw
503 u32 wanted_max_blocks;
504 // Blocks in this range are drawn regardless of number of blocks drawn
505 float wanted_min_range;
506 // Number of blocks rendered is written here by the renderer
508 // Number of blocks that would have been drawn in wanted_range
509 u32 blocks_would_have_drawn;
517 This is the only map class that is able to render itself on screen.
520 class ClientMap : public Map, public scene::ISceneNode
525 MapDrawControl &control,
526 scene::ISceneNode* parent,
527 scene::ISceneManager* mgr,
535 return MAPTYPE_CLIENT;
543 void updateCamera(v3f pos, v3f dir)
545 JMutexAutoLock lock(m_camera_mutex);
546 m_camera_position = pos;
547 m_camera_direction = dir;
551 Forcefully get a sector from somewhere
553 MapSector * emergeSector(v2s16 p);
555 //void deSerializeSector(v2s16 p2d, std::istream &is);
561 virtual void OnRegisterSceneNode();
563 virtual void render()
565 video::IVideoDriver* driver = SceneManager->getVideoDriver();
566 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
567 renderMap(driver, SceneManager->getSceneNodeRenderPass());
570 virtual const core::aabbox3d<f32>& getBoundingBox() const
575 void renderMap(video::IVideoDriver* driver, s32 pass);
578 Methods for setting temporary modifications to nodes for
581 Returns true if something changed.
583 All blocks whose mesh could have been changed are inserted
586 bool setTempMod(v3s16 p, NodeMod mod,
587 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
588 bool clearTempMod(v3s16 p,
589 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
590 // Efficient implementation needs a cache of TempMods
591 //void clearTempMods();
593 void expireMeshes(bool only_daynight_diffed);
596 Update the faces of the given block and blocks on the
599 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
601 // Update meshes that touch the node
602 //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
604 // For debug printing
605 virtual void PrintInfo(std::ostream &out);
607 // Check if sector was drawn on last render()
608 bool sectorWasDrawn(v2s16 p)
610 return (m_last_drawn_sectors.find(p) != NULL);
616 core::aabbox3d<f32> m_box;
618 // This is the master heightmap mesh
619 //scene::SMesh *mesh;
622 MapDrawControl &m_control;
624 v3f m_camera_position;
625 v3f m_camera_direction;
626 JMutex m_camera_mutex;
628 core::map<v2s16, bool> m_last_drawn_sectors;
633 class MapVoxelManipulator : public VoxelManipulator
636 MapVoxelManipulator(Map *map);
637 virtual ~MapVoxelManipulator();
641 VoxelManipulator::clear();
642 m_loaded_blocks.clear();
645 virtual void emerge(VoxelArea a, s32 caller_id=-1);
647 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
653 value = block existed when loaded
655 core::map<v3s16, bool> m_loaded_blocks;
658 class ManualMapVoxelManipulator : public MapVoxelManipulator
661 ManualMapVoxelManipulator(Map *map);
662 virtual ~ManualMapVoxelManipulator();
664 void setMap(Map *map)
667 virtual void emerge(VoxelArea a, s32 caller_id=-1);
669 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
671 // This is much faster with big chunks of generated data
672 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);