diff options
author | Perttu Ahola <celeron55@gmail.com> | 2010-11-27 01:02:21 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2010-11-27 01:02:21 +0200 |
commit | 4e249fb3fbf75f0359758760d88e22aa5b14533c (patch) | |
tree | 323087d05efbd2ace27b316d4f017cf812a31992 /src/map.h | |
download | hax-minetest-server-4e249fb3fbf75f0359758760d88e22aa5b14533c.tar.gz hax-minetest-server-4e249fb3fbf75f0359758760d88e22aa5b14533c.zip |
Initial files
Diffstat (limited to 'src/map.h')
-rw-r--r-- | src/map.h | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/src/map.h b/src/map.h new file mode 100644 index 000000000..ca3b0086b --- /dev/null +++ b/src/map.h @@ -0,0 +1,430 @@ +/* +(c) 2010 Perttu Ahola <celeron55@gmail.com> +*/ + +#ifndef MAP_HEADER +#define MAP_HEADER + +#include <jmutex.h> +#include <jthread.h> +#include <iostream> +#include <malloc.h> + +#ifdef _WIN32 + #include <windows.h> + #define sleep_s(x) Sleep((x*1000)) +#else + #include <unistd.h> + #define sleep_s(x) sleep(x) +#endif + +#include "common_irrlicht.h" +#include "heightmap.h" +#include "loadstatus.h" +#include "mapnode.h" +#include "mapblock.h" +#include "mapsector.h" +#include "constants.h" + +class InvalidFilenameException : public BaseException +{ +public: + InvalidFilenameException(const char *s): + BaseException(s) + {} +}; + +#define MAPTYPE_BASE 0 +#define MAPTYPE_SERVER 1 +#define MAPTYPE_CLIENT 2 + +class Map : public NodeContainer, public Heightmappish +{ +protected: + + std::ostream &m_dout; + + core::map<v2s16, MapSector*> m_sectors; + JMutex m_sector_mutex; + + v3f m_camera_position; + v3f m_camera_direction; + JMutex m_camera_mutex; + + // Be sure to set this to NULL when the cached sector is deleted + MapSector *m_sector_cache; + v2s16 m_sector_cache_p; + + WrapperHeightmap m_hwrapper; + +public: + + v3s16 drawoffset; // for drawbox() + + Map(std::ostream &dout); + virtual ~Map(); + + virtual u16 nodeContainerId() const + { + return NODECONTAINER_ID_MAP; + } + + virtual s32 mapType() const + { + return MAPTYPE_BASE; + } + + void updateCamera(v3f pos, v3f dir) + { + JMutexAutoLock lock(m_camera_mutex); + m_camera_position = pos; + m_camera_direction = dir; + } + + /*void StartUpdater() + { + updater.Start(); + } + + void StopUpdater() + { + updater.setRun(false); + while(updater.IsRunning()) + sleep_s(1); + } + + bool UpdaterIsRunning() + { + return updater.IsRunning(); + }*/ + + static core::aabbox3d<f32> getNodeBox(v3s16 p) + { + return core::aabbox3d<f32>( + (float)p.X * BS - 0.5*BS, + (float)p.Y * BS - 0.5*BS, + (float)p.Z * BS - 0.5*BS, + (float)p.X * BS + 0.5*BS, + (float)p.Y * BS + 0.5*BS, + (float)p.Z * BS + 0.5*BS + ); + } + + //bool sectorExists(v2s16 p); + MapSector * getSectorNoGenerate(v2s16 p2d); + /* + This is overloaded by ClientMap and ServerMap to allow + their differing fetch methods. + */ + virtual MapSector * emergeSector(v2s16 p) = 0; + + // Returns InvalidPositionException if not found + MapBlock * getBlockNoCreate(v3s16 p); + //virtual MapBlock * getBlock(v3s16 p, bool generate=true); + + // Returns InvalidPositionException if not found + f32 getGroundHeight(v2s16 p, bool generate=false); + void setGroundHeight(v2s16 p, f32 y, bool generate=false); + + // Returns InvalidPositionException if not found + bool isNodeUnderground(v3s16 p); + + // virtual from NodeContainer + bool isValidPosition(v3s16 p) + { + v3s16 blockpos = getNodeBlockPos(p); + MapBlock *blockref; + try{ + blockref = getBlockNoCreate(blockpos); + } + catch(InvalidPositionException &e) + { + return false; + } + return true; + /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + bool is_valid = blockref->isValidPosition(relpos); + return is_valid;*/ + } + + // virtual from NodeContainer + MapNode getNode(v3s16 p) + { + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlockNoCreate(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + + return blockref->getNode(relpos); + } + + // virtual from NodeContainer + void setNode(v3s16 p, MapNode & n) + { + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlockNoCreate(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + blockref->setNode(relpos, n); + } + + /*MapNode getNodeGenerate(v3s16 p) + { + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlock(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + + return blockref->getNode(relpos); + }*/ + + /*void setNodeGenerate(v3s16 p, MapNode & n) + { + v3s16 blockpos = getNodeBlockPos(p); + MapBlock * blockref = getBlock(blockpos); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + blockref->setNode(relpos, n); + }*/ + + void unspreadLight(core::map<v3s16, u8> & from_nodes, + core::map<v3s16, bool> & light_sources, + core::map<v3s16, MapBlock*> & modified_blocks); + + void unLightNeighbors(v3s16 pos, u8 lightwas, + core::map<v3s16, bool> & light_sources, + core::map<v3s16, MapBlock*> & modified_blocks); + + void spreadLight(core::map<v3s16, bool> & from_nodes, + core::map<v3s16, MapBlock*> & modified_blocks); + + void lightNeighbors(v3s16 pos, + core::map<v3s16, MapBlock*> & modified_blocks); + + v3s16 getBrightestNeighbour(v3s16 p); + + s16 propagateSunlight(v3s16 start, + core::map<v3s16, MapBlock*> & modified_blocks); + + void updateLighting(core::map<v3s16, MapBlock*> & a_blocks, + core::map<v3s16, MapBlock*> & modified_blocks); + + /* + These handle lighting but not faces. + */ + void addNodeAndUpdate(v3s16 p, MapNode n, + core::map<v3s16, MapBlock*> &modified_blocks); + void removeNodeAndUpdate(v3s16 p, + core::map<v3s16, MapBlock*> &modified_blocks); + + /* + Updates the faces of the given block and blocks on the + leading edge. + */ + void updateMeshes(v3s16 blockpos); + + //core::aabbox3d<s16> getDisplayedBlockArea(); + + //bool updateChangedVisibleArea(); + + virtual void save(bool only_changed){assert(0);}; + + /* + Updates usage timers + */ + void timerUpdate(float dtime); + + // Takes cache into account + // sector mutex should be locked when calling + void deleteSectors(core::list<v2s16> &list, bool only_blocks); + + // Returns count of deleted sectors + u32 deleteUnusedSectors(float timeout, bool only_blocks=false, + core::list<v3s16> *deleted_blocks=NULL); + + // For debug printing + virtual void PrintInfo(std::ostream &out); +}; + +struct MapgenParams +{ + MapgenParams() + { + heightmap_blocksize = 64; + height_randmax = "constant 70.0"; + height_randfactor = "constant 0.6"; + height_base = "linear 0 80 0"; + plants_amount = "1.0"; + } + s16 heightmap_blocksize; + std::string height_randmax; + std::string height_randfactor; + std::string height_base; + std::string plants_amount; +}; + +class ServerMap : public Map +{ +public: + /* + savedir: directory to which map data should be saved + */ + ServerMap(std::string savedir, MapgenParams params); + ~ServerMap(); + + s32 mapType() const + { + return MAPTYPE_SERVER; + } + + /* + Forcefully get a sector from somewhere + */ + MapSector * emergeSector(v2s16 p); + /* + Forcefully get a block from somewhere. + + Exceptions: + - InvalidPositionException: possible if only_from_disk==true + + changed_blocks: + - All already existing blocks that were modified are added. + - If found on disk, nothing will be added. + - If generated, the new block will not be included. + + lighting_invalidated_blocks: + - All blocks that have heavy-to-calculate lighting changes + are added. + - updateLighting() should be called for these. + + - A block that is in changed_blocks may not be in + lighting_invalidated_blocks. + */ + MapBlock * emergeBlock( + v3s16 p, + bool only_from_disk, + core::map<v3s16, MapBlock*> &changed_blocks, + core::map<v3s16, MapBlock*> &lighting_invalidated_blocks + ); + + void createDir(std::string path); + void createSaveDir(); + // returns something like "xxxxxxxx" + std::string getSectorSubDir(v2s16 pos); + // returns something like "map/sectors/xxxxxxxx" + std::string getSectorDir(v2s16 pos); + std::string createSectorDir(v2s16 pos); + // dirname: final directory name + v2s16 getSectorPos(std::string dirname); + v3s16 getBlockPos(std::string sectordir, std::string blockfile); + + void save(bool only_changed); + void loadAll(); + + void saveMasterHeightmap(); + void loadMasterHeightmap(); + + // The sector mutex should be locked when calling most of these + + // This only saves sector-specific data such as the heightmap + // (no MapBlocks) + void saveSectorMeta(ServerMapSector *sector); + MapSector* loadSectorMeta(std::string dirname); + + // Full load of a sector including all blocks. + // returns true on success, false on failure. + bool loadSectorFull(v2s16 p2d); + // If sector is not found in memory, try to load it from disk. + // Returns true if sector now resides in memory + //bool deFlushSector(v2s16 p2d); + + void saveBlock(MapBlock *block); + // This will generate a sector with getSector if not found. + void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector); + + // Gets from master heightmap + void getSectorCorners(v2s16 p2d, s16 *corners); + + // For debug printing + virtual void PrintInfo(std::ostream &out); + +private: + UnlimitedHeightmap *m_heightmap; + std::string m_savedir; + bool m_map_saving_enabled; +}; + +class Client; + +class ClientMap : public Map, public scene::ISceneNode +{ +public: + ClientMap( + Client *client, + video::SMaterial *materials, + scene::ISceneNode* parent, + scene::ISceneManager* mgr, + s32 id + ); + + ~ClientMap(); + + s32 mapType() const + { + return MAPTYPE_CLIENT; + } + + /* + Forcefully get a sector from somewhere + */ + MapSector * emergeSector(v2s16 p); + + void deSerializeSector(v2s16 p2d, std::istream &is); + + /* + ISceneNode methods + */ + + virtual void OnRegisterSceneNode() + { + if(IsVisible) + { + //SceneManager->registerNodeForRendering(this, scene::ESNRP_SKY_BOX); + SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); + SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); + } + + ISceneNode::OnRegisterSceneNode(); + } + + virtual void render() + { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + renderMap(driver, m_materials, SceneManager->getSceneNodeRenderPass()); + } + + virtual const core::aabbox3d<f32>& getBoundingBox() const + { + return m_box; + } + + void renderMap(video::IVideoDriver* driver, + video::SMaterial *materials, s32 pass); + + // Update master heightmap mesh + void updateMesh(); + + // For debug printing + virtual void PrintInfo(std::ostream &out); + +private: + Client *m_client; + + video::SMaterial *m_materials; + + core::aabbox3d<f32> m_box; + + // This is the master heightmap mesh + scene::SMesh *mesh; + JMutex mesh_mutex; +}; + +#endif + |