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>
29 #include "common_irrlicht.h"
31 #include "mapblock_nodemod.h"
32 #include "constants.h"
34 #include "utility.h" // Needed for UniqueQueue, a member of Map
41 class ServerMapSector;
42 class ClientMapSector;
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,
67 // Anything else (modified_blocks are set unsent)
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, IGameDef *gamedef);
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 // Same as the above (there exists no lock anymore)
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);
162 /* Server overrides */
163 virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true)
164 { return getBlockNoCreateNoEx(p); }
166 // Returns InvalidPositionException if not found
167 bool isNodeUnderground(v3s16 p);
169 bool isValidPosition(v3s16 p);
171 // throws InvalidPositionException if not found
172 MapNode getNode(v3s16 p);
174 // throws InvalidPositionException if not found
175 void setNode(v3s16 p, MapNode & n);
177 // Returns a CONTENT_IGNORE node if not found
178 MapNode getNodeNoEx(v3s16 p);
180 void unspreadLight(enum LightBank bank,
181 core::map<v3s16, u8> & from_nodes,
182 core::map<v3s16, bool> & light_sources,
183 core::map<v3s16, MapBlock*> & modified_blocks);
185 void unLightNeighbors(enum LightBank bank,
186 v3s16 pos, u8 lightwas,
187 core::map<v3s16, bool> & light_sources,
188 core::map<v3s16, MapBlock*> & modified_blocks);
190 void spreadLight(enum LightBank bank,
191 core::map<v3s16, bool> & from_nodes,
192 core::map<v3s16, MapBlock*> & modified_blocks);
194 void lightNeighbors(enum LightBank bank,
196 core::map<v3s16, MapBlock*> & modified_blocks);
198 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
200 s16 propagateSunlight(v3s16 start,
201 core::map<v3s16, MapBlock*> & modified_blocks);
203 void updateLighting(enum LightBank bank,
204 core::map<v3s16, MapBlock*> & a_blocks,
205 core::map<v3s16, MapBlock*> & modified_blocks);
207 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
208 core::map<v3s16, MapBlock*> & modified_blocks);
211 These handle lighting but not faces.
213 void addNodeAndUpdate(v3s16 p, MapNode n,
214 core::map<v3s16, MapBlock*> &modified_blocks, std::string &player_name);
215 void removeNodeAndUpdate(v3s16 p,
216 core::map<v3s16, MapBlock*> &modified_blocks);
219 Wrappers for the latter ones.
221 Return true if succeeded, false if not.
223 bool addNodeWithEvent(v3s16 p, MapNode n);
224 bool removeNodeWithEvent(v3s16 p);
227 Takes the blocks at the edges into account
229 bool dayNightDiffed(v3s16 blockpos);
231 //core::aabbox3d<s16> getDisplayedBlockArea();
233 //bool updateChangedVisibleArea();
235 // Call these before and after saving of many blocks
236 virtual void beginSave() {return;};
237 virtual void endSave() {return;};
239 virtual void save(bool only_changed){assert(0);};
241 // Server implements this.
242 // Client leaves it as no-op.
243 virtual void saveBlock(MapBlock *block){};
246 Updates usage timers and unloads unused blocks and sectors.
247 Saves modified blocks before unloading on MAPTYPE_SERVER.
249 void timerUpdate(float dtime, float unload_timeout,
250 core::list<v3s16> *unloaded_blocks=NULL);
252 // Deletes sectors and their blocks from memory
253 // Takes cache into account
254 // If deleted sector is in sector cache, clears cache
255 void deleteSectors(core::list<v2s16> &list);
260 = flush changed to disk and delete from memory, if usage timer of
261 block is more than timeout
263 void unloadUnusedData(float timeout,
264 core::list<v3s16> *deleted_blocks=NULL);
267 // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
268 virtual void PrintInfo(std::ostream &out);
270 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
274 These are basically coordinate wrappers to MapBlock
277 NodeMetadata* getNodeMetadata(v3s16 p);
278 void setNodeMetadata(v3s16 p, NodeMetadata *meta);
279 void removeNodeMetadata(v3s16 p);
280 void nodeMetadataStep(float dtime,
281 core::map<v3s16, MapBlock*> &changed_blocks);
286 core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
294 std::ostream &m_dout; // A bit deprecated, could be removed
298 core::map<MapEventReceiver*, bool> m_event_receivers;
300 core::map<v2s16, MapSector*> m_sectors;
302 // Be sure to set this to NULL when the cached sector is deleted
303 MapSector *m_sector_cache;
304 v2s16 m_sector_cache_p;
306 // Queued transforming water nodes
307 UniqueQueue<v3s16> m_transforming_liquid;
313 This is the only map class that is able to generate map.
316 class ServerMap : public Map
320 savedir: directory to which map data should be saved
322 ServerMap(std::string savedir, IGameDef *gamedef);
327 return MAPTYPE_SERVER;
331 Get a sector from somewhere.
333 - Check disk (doesn't load blocks)
336 ServerMapSector * createSector(v2s16 p);
339 Blocks are generated by using these and makeBlock().
341 void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
342 MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
343 core::map<v3s16, MapBlock*> &changed_blocks);
345 // A non-threaded wrapper to the above
346 MapBlock * generateBlock(
348 core::map<v3s16, MapBlock*> &modified_blocks
352 Get a block from somewhere.
356 MapBlock * createBlock(v3s16 p);
359 Forcefully get a block from somewhere.
364 MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
366 // Helper for placing objects on ground level
367 s16 findGroundLevel(v2s16 p2d);
370 Misc. helper functions for fiddling with directory and file
373 void createDirs(std::string path);
374 // returns something like "map/sectors/xxxxxxxx"
375 std::string getSectorDir(v2s16 pos, int layout = 2);
376 // dirname: final directory name
377 v2s16 getSectorPos(std::string dirname);
378 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
379 static std::string getBlockFilename(v3s16 p);
384 // Create the database structure
385 void createDatabase();
386 // Verify we can read/write to the database
387 void verifyDatabase();
388 // Get an integer suitable for a block
389 static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
390 static v3s16 getIntegerAsBlock(sqlite3_int64 i);
392 // Returns true if the database file does not exist
393 bool loadFromFolders();
395 // Call these before and after saving of blocks
399 void save(bool only_changed);
402 void listAllLoadableBlocks(core::list<v3s16> &dst);
404 // Saves map seed and possibly other stuff
408 /*void saveChunkMeta();
409 void loadChunkMeta();*/
411 // The sector mutex should be locked when calling most of these
413 // This only saves sector-specific data such as the heightmap
415 // DEPRECATED? Sectors have no metadata anymore.
416 void saveSectorMeta(ServerMapSector *sector);
417 MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
418 bool loadSectorMeta(v2s16 p2d);
420 // Full load of a sector including all blocks.
421 // returns true on success, false on failure.
422 bool loadSectorFull(v2s16 p2d);
423 // If sector is not found in memory, try to load it from disk.
424 // Returns true if sector now resides in memory
425 //bool deFlushSector(v2s16 p2d);
427 void saveBlock(MapBlock *block);
428 // This will generate a sector with getSector if not found.
429 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
430 MapBlock* loadBlock(v3s16 p);
432 void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
434 // For debug printing
435 virtual void PrintInfo(std::ostream &out);
437 bool isSavingEnabled(){ return m_map_saving_enabled; }
439 u64 getSeed(){ return m_seed; }
442 // Seed used for all kinds of randomness in generation
445 std::string m_savedir;
446 bool m_map_saving_enabled;
449 // Chunk size in MapSectors
450 // If 0, chunks are disabled.
453 core::map<v2s16, MapChunk*> m_chunks;
457 Metadata is re-written on disk only if this is true.
458 This is reset to false when written on disk.
460 bool m_map_metadata_changed;
463 SQLite database and statements
466 sqlite3_stmt *m_database_read;
467 sqlite3_stmt *m_database_write;
468 sqlite3_stmt *m_database_list;
477 struct MapDrawControl
482 wanted_max_blocks(0),
485 blocks_would_have_drawn(0)
488 // Overrides limits by drawing everything
490 // Wanted drawing range
492 // Maximum number of blocks to draw
493 u32 wanted_max_blocks;
494 // Blocks in this range are drawn regardless of number of blocks drawn
495 float wanted_min_range;
496 // Number of blocks rendered is written here by the renderer
498 // Number of blocks that would have been drawn in wanted_range
499 u32 blocks_would_have_drawn;
503 class ITextureSource;
508 This is the only map class that is able to render itself on screen.
511 class ClientMap : public Map, public scene::ISceneNode
517 MapDrawControl &control,
518 scene::ISceneNode* parent,
519 scene::ISceneManager* mgr,
527 return MAPTYPE_CLIENT;
535 void updateCamera(v3f pos, v3f dir, f32 fov)
537 JMutexAutoLock lock(m_camera_mutex);
538 m_camera_position = pos;
539 m_camera_direction = dir;
544 Forcefully get a sector from somewhere
546 MapSector * emergeSector(v2s16 p);
548 //void deSerializeSector(v2s16 p2d, std::istream &is);
554 virtual void OnRegisterSceneNode();
556 virtual void render()
558 video::IVideoDriver* driver = SceneManager->getVideoDriver();
559 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
560 renderMap(driver, SceneManager->getSceneNodeRenderPass());
563 virtual const core::aabbox3d<f32>& getBoundingBox() const
568 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
592 leading edge, without threading. Rarely used.
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;
622 JMutex m_camera_mutex;
624 core::map<v2s16, bool> m_last_drawn_sectors;
629 class MapVoxelManipulator : public VoxelManipulator
632 MapVoxelManipulator(Map *map);
633 virtual ~MapVoxelManipulator();
637 VoxelManipulator::clear();
638 m_loaded_blocks.clear();
641 virtual void emerge(VoxelArea a, s32 caller_id=-1);
643 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
649 value = block existed when loaded
651 core::map<v3s16, bool> m_loaded_blocks;
654 class ManualMapVoxelManipulator : public MapVoxelManipulator
657 ManualMapVoxelManipulator(Map *map);
658 virtual ~ManualMapVoxelManipulator();
660 void setMap(Map *map)
663 virtual void emerge(VoxelArea a, s32 caller_id=-1);
665 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
667 // This is much faster with big chunks of generated data
668 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);