3 Copyright (C) 2010 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"
44 Some exposed functions
47 double base_rock_level_2d(u64 seed, v2f p);
48 bool get_have_sand_coast(u64 seed, v2f p);
49 bool get_have_sand_ground(u64 seed, v2f p);
50 double get_turbulence_factor_2d(u64 seed, v2f p);
55 #define MAPTYPE_BASE 0
56 #define MAPTYPE_SERVER 1
57 #define MAPTYPE_CLIENT 2
59 enum MapEditEventType{
67 MapEditEventType type;
70 core::map<v3s16, bool> modified_blocks;
71 u16 already_known_by_peer;
75 already_known_by_peer(0)
79 MapEditEvent * clone()
81 MapEditEvent *event = new MapEditEvent();
85 for(core::map<v3s16, bool>::Iterator
86 i = modified_blocks.getIterator();
87 i.atEnd()==false; i++)
89 v3s16 p = i.getNode()->getKey();
90 bool v = i.getNode()->getValue();
91 event->modified_blocks.insert(p, v);
97 class MapEventReceiver
100 // event shall be deleted by caller after the call.
101 virtual void onMapEditEvent(MapEditEvent *event) = 0;
104 class Map : public NodeContainer
108 Map(std::ostream &dout);
111 virtual u16 nodeContainerId() const
113 return NODECONTAINER_ID_MAP;
116 virtual s32 mapType() const
122 Drop (client) or delete (server) the map.
129 void addEventReceiver(MapEventReceiver *event_receiver);
130 void removeEventReceiver(MapEventReceiver *event_receiver);
131 // event shall be deleted by caller after the call.
132 void dispatchEvent(MapEditEvent *event);
134 // On failure returns NULL
135 MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
136 // On failure returns NULL
137 MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
138 // On failure throws InvalidPositionException
139 MapSector * getSectorNoGenerate(v2s16 p2d);
140 // Gets an existing sector or creates an empty one
141 //MapSector * getSectorCreate(v2s16 p2d);
144 This is overloaded by ClientMap and ServerMap to allow
145 their differing fetch methods.
147 virtual MapSector * emergeSector(v2s16 p){ return NULL; }
148 virtual MapSector * emergeSector(v2s16 p,
149 core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
151 // Returns InvalidPositionException if not found
152 MapBlock * getBlockNoCreate(v3s16 p);
153 // Returns NULL if not found
154 MapBlock * getBlockNoCreateNoEx(v3s16 p);
155 // Gets an existing block or creates an empty one
156 //MapBlock * getBlockCreate(v3s16 p);
158 // Returns InvalidPositionException if not found
159 bool isNodeUnderground(v3s16 p);
161 // virtual from NodeContainer
162 bool isValidPosition(v3s16 p)
164 v3s16 blockpos = getNodeBlockPos(p);
167 blockref = getBlockNoCreate(blockpos);
169 catch(InvalidPositionException &e)
174 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
175 bool is_valid = blockref->isValidPosition(relpos);
179 // virtual from NodeContainer
180 // throws InvalidPositionException if not found
181 MapNode getNode(v3s16 p)
183 v3s16 blockpos = getNodeBlockPos(p);
184 MapBlock * blockref = getBlockNoCreate(blockpos);
185 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
187 return blockref->getNodeNoCheck(relpos);
190 // virtual from NodeContainer
191 // throws InvalidPositionException if not found
192 void setNode(v3s16 p, MapNode & n)
194 v3s16 blockpos = getNodeBlockPos(p);
195 MapBlock * blockref = getBlockNoCreate(blockpos);
196 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
197 blockref->setNodeNoCheck(relpos, n);
200 // Returns a CONTENT_IGNORE node if not found
201 MapNode getNodeNoEx(v3s16 p)
204 v3s16 blockpos = getNodeBlockPos(p);
205 MapBlock * blockref = getBlockNoCreate(blockpos);
206 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
208 return blockref->getNodeNoCheck(relpos);
210 catch(InvalidPositionException &e)
212 return MapNode(CONTENT_IGNORE);
216 void unspreadLight(enum LightBank bank,
217 core::map<v3s16, u8> & from_nodes,
218 core::map<v3s16, bool> & light_sources,
219 core::map<v3s16, MapBlock*> & modified_blocks);
221 void unLightNeighbors(enum LightBank bank,
222 v3s16 pos, u8 lightwas,
223 core::map<v3s16, bool> & light_sources,
224 core::map<v3s16, MapBlock*> & modified_blocks);
226 void spreadLight(enum LightBank bank,
227 core::map<v3s16, bool> & from_nodes,
228 core::map<v3s16, MapBlock*> & modified_blocks);
230 void lightNeighbors(enum LightBank bank,
232 core::map<v3s16, MapBlock*> & modified_blocks);
234 v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
236 s16 propagateSunlight(v3s16 start,
237 core::map<v3s16, MapBlock*> & modified_blocks);
239 void updateLighting(enum LightBank bank,
240 core::map<v3s16, MapBlock*> & a_blocks,
241 core::map<v3s16, MapBlock*> & modified_blocks);
243 void updateLighting(core::map<v3s16, MapBlock*> & a_blocks,
244 core::map<v3s16, MapBlock*> & modified_blocks);
247 These handle lighting but not faces.
249 void addNodeAndUpdate(v3s16 p, MapNode n,
250 core::map<v3s16, MapBlock*> &modified_blocks);
251 void removeNodeAndUpdate(v3s16 p,
252 core::map<v3s16, MapBlock*> &modified_blocks);
255 Wrappers for the latter ones.
257 Return true if succeeded, false if not.
259 bool addNodeWithEvent(v3s16 p, MapNode n);
260 bool removeNodeWithEvent(v3s16 p);
263 Takes the blocks at the edges into account
265 bool dayNightDiffed(v3s16 blockpos);
267 //core::aabbox3d<s16> getDisplayedBlockArea();
269 //bool updateChangedVisibleArea();
271 virtual void save(bool only_changed){assert(0);};
276 void timerUpdate(float dtime);
278 // Takes cache into account
279 // sector mutex should be locked when calling
280 void deleteSectors(core::list<v2s16> &list, bool only_blocks);
282 // Returns count of deleted sectors
283 u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
284 core::list<v3s16> *deleted_blocks=NULL);
286 // For debug printing
287 virtual void PrintInfo(std::ostream &out);
289 void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
297 std::ostream &m_dout;
299 core::map<MapEventReceiver*, bool> m_event_receivers;
301 // Mutex is important because on client map is accessed asynchronously
302 core::map<v2s16, MapSector*> m_sectors;
303 JMutex m_sector_mutex;
305 // Be sure to set this to NULL when the cached sector is deleted
306 MapSector *m_sector_cache;
307 v2s16 m_sector_cache_p;
309 //WrapperHeightmap m_hwrapper;
311 // Queued transforming water nodes
312 UniqueQueue<v3s16> m_transforming_liquid;
318 This is the only map class that is able to generate map.
321 class ServerMap : public Map
325 savedir: directory to which map data should be saved
327 ServerMap(std::string savedir);
332 return MAPTYPE_SERVER;
339 // Returns the position of the chunk where the sector is in
340 v2s16 sector_to_chunk(v2s16 sectorpos)
342 sectorpos.X += m_chunksize / 2;
343 sectorpos.Y += m_chunksize / 2;
344 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
348 // Returns the position of the (0,0) sector of the chunk
349 v2s16 chunk_to_sector(v2s16 chunkpos)
352 chunkpos.X * m_chunksize,
353 chunkpos.Y * m_chunksize
355 sectorpos.X -= m_chunksize / 2;
356 sectorpos.Y -= m_chunksize / 2;
363 MapChunk *getChunk(v2s16 chunkpos)
365 core::map<v2s16, MapChunk*>::Node *n;
366 n = m_chunks.find(chunkpos);
369 return n->getValue();
373 True if the chunk and its neighbors are fully generated.
374 It means the chunk will not be touched in the future by the
375 generator. If false, generateChunk will make it true.
377 bool chunkNonVolatile(v2s16 chunkpos)
379 /*for(s16 x=-1; x<=1; x++)
380 for(s16 y=-1; y<=1; y++)*/
384 v2s16 chunkpos0 = chunkpos + v2s16(x,y);
385 MapChunk *chunk = getChunk(chunkpos);
388 if(chunk->getGenLevel() != GENERATED_FULLY)
397 All chunks touching this one can be altered also.
399 MapChunk* generateChunkRaw(v2s16 chunkpos,
400 core::map<v3s16, MapBlock*> &changed_blocks,
404 Generate a chunk and its neighbors so that it won't be touched
407 MapChunk* generateChunk(v2s16 chunkpos,
408 core::map<v3s16, MapBlock*> &changed_blocks);
413 This is mainly called by generateChunkRaw.
415 //ServerMapSector * generateSector(v2s16 p);
418 Get a sector from somewhere.
420 - Check disk (loads blocks also)
423 ServerMapSector * createSector(v2s16 p);
426 Get a sector from somewhere.
428 - Check disk (loads blocks also)
431 MapSector * emergeSector(v2s16 p,
432 core::map<v3s16, MapBlock*> &changed_blocks);
434 MapSector * emergeSector(v2s16 p)
436 core::map<v3s16, MapBlock*> changed_blocks;
437 return emergeSector(p, changed_blocks);
440 MapBlock * generateBlock(
442 MapBlock *original_dummy,
443 ServerMapSector *sector,
444 core::map<v3s16, MapBlock*> &changed_blocks,
445 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
449 Get a block from somewhere.
453 MapBlock * createBlock(v3s16 p);
456 only_from_disk, changed_blocks and lighting_invalidated_blocks
457 are not properly used by the new map generator.
459 MapBlock * emergeBlock(
462 core::map<v3s16, MapBlock*> &changed_blocks,
463 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
468 Forcefully get a block from somewhere.
471 - InvalidPositionException: possible if only_from_disk==true
474 - All already existing blocks that were modified are added.
475 - If found on disk, nothing will be added.
476 - If generated, the new block will not be included.
478 lighting_invalidated_blocks:
479 - All blocks that have heavy-to-calculate lighting changes
481 - updateLighting() should be called for these.
483 - A block that is in changed_blocks may not be in
484 lighting_invalidated_blocks.
486 MapBlock * emergeBlock(
489 core::map<v3s16, MapBlock*> &changed_blocks,
490 core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
494 // Helper for placing objects on ground level
495 s16 findGroundLevel(v2s16 p2d);
498 Misc. helper functions for fiddling with directory and file
501 void createDir(std::string path);
502 void createSaveDir();
503 // returns something like "xxxxxxxx"
504 std::string getSectorSubDir(v2s16 pos);
505 // returns something like "map/sectors/xxxxxxxx"
506 std::string getSectorDir(v2s16 pos);
507 std::string createSectorDir(v2s16 pos);
508 // dirname: final directory name
509 v2s16 getSectorPos(std::string dirname);
510 v3s16 getBlockPos(std::string sectordir, std::string blockfile);
512 void save(bool only_changed);
515 // Saves map seed and possibly other stuff
519 void saveChunkMeta();
520 void loadChunkMeta();
522 // The sector mutex should be locked when calling most of these
524 // This only saves sector-specific data such as the heightmap
526 // DEPRECATED? Sectors have no metadata anymore.
527 void saveSectorMeta(ServerMapSector *sector);
528 MapSector* loadSectorMeta(std::string dirname);
530 // Full load of a sector including all blocks.
531 // returns true on success, false on failure.
532 bool loadSectorFull(v2s16 p2d);
533 // If sector is not found in memory, try to load it from disk.
534 // Returns true if sector now resides in memory
535 //bool deFlushSector(v2s16 p2d);
537 void saveBlock(MapBlock *block);
538 // This will generate a sector with getSector if not found.
539 void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
541 // For debug printing
542 virtual void PrintInfo(std::ostream &out);
544 bool isSavingEnabled(){ return m_map_saving_enabled; }
546 u64 getSeed(){ return m_seed; }
549 // Seed used for all kinds of randomness
552 std::string m_savedir;
553 bool m_map_saving_enabled;
555 // Chunk size in MapSectors
558 core::map<v2s16, MapChunk*> m_chunks;
567 struct MapDrawControl
572 wanted_max_blocks(0),
575 blocks_would_have_drawn(0)
578 // Overrides limits by drawing everything
580 // Wanted drawing range
582 // Maximum number of blocks to draw
583 u32 wanted_max_blocks;
584 // Blocks in this range are drawn regardless of number of blocks drawn
585 float wanted_min_range;
586 // Number of blocks rendered is written here by the renderer
588 // Number of blocks that would have been drawn in wanted_range
589 u32 blocks_would_have_drawn;
597 This is the only map class that is able to render itself on screen.
600 class ClientMap : public Map, public scene::ISceneNode
605 MapDrawControl &control,
606 scene::ISceneNode* parent,
607 scene::ISceneManager* mgr,
615 return MAPTYPE_CLIENT;
623 void updateCamera(v3f pos, v3f dir)
625 JMutexAutoLock lock(m_camera_mutex);
626 m_camera_position = pos;
627 m_camera_direction = dir;
631 Forcefully get a sector from somewhere
633 MapSector * emergeSector(v2s16 p);
635 void deSerializeSector(v2s16 p2d, std::istream &is);
641 virtual void OnRegisterSceneNode();
643 virtual void render()
645 video::IVideoDriver* driver = SceneManager->getVideoDriver();
646 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
647 renderMap(driver, SceneManager->getSceneNodeRenderPass());
650 virtual const core::aabbox3d<f32>& getBoundingBox() const
655 void renderMap(video::IVideoDriver* driver, s32 pass);
658 Methods for setting temporary modifications to nodes for
661 Returns true if something changed.
663 All blocks whose mesh could have been changed are inserted
666 bool setTempMod(v3s16 p, NodeMod mod,
667 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
668 bool clearTempMod(v3s16 p,
669 core::map<v3s16, MapBlock*> *affected_blocks=NULL);
670 // Efficient implementation needs a cache of TempMods
671 //void clearTempMods();
673 void expireMeshes(bool only_daynight_diffed);
676 Update the faces of the given block and blocks on the
679 void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
681 // Update meshes that touch the node
682 void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
684 // For debug printing
685 virtual void PrintInfo(std::ostream &out);
690 core::aabbox3d<f32> m_box;
692 // This is the master heightmap mesh
693 //scene::SMesh *mesh;
696 MapDrawControl &m_control;
698 v3f m_camera_position;
699 v3f m_camera_direction;
700 JMutex m_camera_mutex;
706 class MapVoxelManipulator : public VoxelManipulator
709 MapVoxelManipulator(Map *map);
710 virtual ~MapVoxelManipulator();
714 VoxelManipulator::clear();
715 m_loaded_blocks.clear();
718 virtual void emerge(VoxelArea a, s32 caller_id=-1);
720 void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
726 value = block existed when loaded
728 core::map<v3s16, bool> m_loaded_blocks;
731 class ManualMapVoxelManipulator : public MapVoxelManipulator
734 ManualMapVoxelManipulator(Map *map);
735 virtual ~ManualMapVoxelManipulator();
737 virtual void emerge(VoxelArea a, s32 caller_id=-1);
739 void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
741 // This is much faster with big chunks of generated data
742 void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);