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/mapsector.h | |
download | minetest-4e249fb3fbf75f0359758760d88e22aa5b14533c.tar.gz minetest-4e249fb3fbf75f0359758760d88e22aa5b14533c.tar.bz2 minetest-4e249fb3fbf75f0359758760d88e22aa5b14533c.zip |
Initial files
Diffstat (limited to 'src/mapsector.h')
-rw-r--r-- | src/mapsector.h | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/mapsector.h b/src/mapsector.h new file mode 100644 index 000000000..196a129c3 --- /dev/null +++ b/src/mapsector.h @@ -0,0 +1,318 @@ +/* +(c) 2010 Perttu Ahola <celeron55@gmail.com> +*/ + +#ifndef MAPSECTOR_HEADER +#define MAPSECTOR_HEADER + +#include <jmutex.h> +#include "common_irrlicht.h" +#include "mapblock.h" +#include "heightmap.h" +#include "exceptions.h" + +/* + This is an Y-wise stack of MapBlocks. +*/ + +#define WATER_LEVEL (-5) + +#define SECTOR_OBJECT_TEST 0 +#define SECTOR_OBJECT_TREE_1 1 +#define SECTOR_OBJECT_BUSH_1 2 + +#define MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT 4 + +#define MAPSECTOR_SERVER 0 +#define MAPSECTOR_CLIENT 1 + +class MapSector: public NodeContainer, public Heightmappish +{ +public: + + MapSector(NodeContainer *parent, v2s16 pos); + virtual ~MapSector(); + + virtual u16 nodeContainerId() const + { + return NODECONTAINER_ID_MAPSECTOR; + } + + virtual u32 getId() const = 0; + + void deleteBlocks(); + + v2s16 getPos() + { + return m_pos; + } + + MapBlock * getBlockNoCreate(s16 y); + MapBlock * createBlankBlockNoInsert(s16 y); + MapBlock * createBlankBlock(s16 y); + //MapBlock * getBlock(s16 y, bool generate=true); + + void insertBlock(MapBlock *block); + + // This is used to remove a dummy from the sector while generating it. + // Block is only removed from internal container, not deleted. + void removeBlock(MapBlock *block); + + /* + This might not be a thread-safe depending on the day. + See the implementation. + */ + void getBlocks(core::list<MapBlock*> &dest); + + /* + If all nodes in area can be accessed, returns true and + adds all blocks in area to blocks. + + If all nodes in area cannot be accessed, returns false. + + The implementation of this is quite slow + + if blocks==NULL; it is not accessed at all. + */ + bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes, + core::map<s16, MapBlock*> *blocks) + { + core::map<s16, MapBlock*> bs; + + v3s16 p_min = getNodeBlockPos(p_min_nodes); + v3s16 p_max = getNodeBlockPos(p_max_nodes); + if(p_min.X != 0 || p_min.Z != 0 + || p_max.X != 0 || p_max.Z != 0) + return false; + v3s16 y; + for(s16 y=p_min.Y; y<=p_max.Y; y++) + { + try{ + MapBlock *block = getBlockNoCreate(y); + if(block->isDummy()) + return false; + if(blocks!=NULL) + bs[y] = block; + } + catch(InvalidPositionException &e) + { + return false; + } + } + + if(blocks!=NULL) + { + for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator(); + i.atEnd()==false; i++) + { + MapBlock *block = i.getNode()->getValue(); + s16 y = i.getNode()->getKey(); + blocks->insert(y, block); + } + } + return true; + } + + void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes, + core::map<v3s16, MapBlock*> &blocks) + { + v3s16 p_min = getNodeBlockPos(p_min_nodes); + v3s16 p_max = getNodeBlockPos(p_max_nodes); + v3s16 y; + for(s16 y=p_min.Y; y<=p_max.Y; y++) + { + try{ + MapBlock *block = getBlockNoCreate(y); + blocks.insert(block->getPos(), block); + } + catch(InvalidPositionException &e) + { + } + } + } + + // virtual from NodeContainer + bool isValidPosition(v3s16 p) + { + v3s16 blockpos = getNodeBlockPos(p); + + if(blockpos.X != 0 || blockpos.Z != 0) + return false; + + MapBlock *blockref; + try{ + blockref = getBlockNoCreate(blockpos.Y); + } + catch(InvalidPositionException &e) + { + return false; + } + + return true; + } + + // virtual from NodeContainer + MapNode getNode(v3s16 p) + { + v3s16 blockpos = getNodeBlockPos(p); + if(blockpos.X != 0 || blockpos.Z != 0) + throw InvalidPositionException + ("MapSector only allows Y"); + + MapBlock * blockref = getBlockNoCreate(blockpos.Y); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + + return blockref->getNode(relpos); + } + // virtual from NodeContainer + void setNode(v3s16 p, MapNode & n) + { + v3s16 blockpos = getNodeBlockPos(p); + if(blockpos.X != 0 || blockpos.Z != 0) + throw InvalidPositionException + ("MapSector only allows Y"); + + MapBlock * blockref = getBlockNoCreate(blockpos.Y); + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; + blockref->setNode(relpos, n); + } + + virtual f32 getGroundHeight(v2s16 p, bool generate=false) + { + return GROUNDHEIGHT_NOTFOUND_SETVALUE; + } + virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false) + { + } + + // When true, sector metadata is changed from the one on disk + // (sector metadata = all but blocks) + // Basically, this should be changed to true in every setter method + bool differs_from_disk; + + // Counts seconds from last usage. + // Sector can be deleted from memory after some time of inactivity. + // NOTE: It has to be made very sure no other thread is accessing + // the sector and it doesn't remain in any cache when + // deleting it. + float usage_timer; + +protected: + + // The pile of MapBlocks + core::map<s16, MapBlock*> m_blocks; + //JMutex m_blocks_mutex; // For public access functions + + NodeContainer *m_parent; + // Position on parent (in MapBlock widths) + v2s16 m_pos; + + // Be sure to set this to NULL when the cached block is deleted + MapBlock *m_block_cache; + s16 m_block_cache_y; + + // This is used for protecting m_blocks + JMutex m_mutex; + + /* + Private methods + */ + MapBlock *getBlockBuffered(s16 y); + +}; + +class ServerMapSector : public MapSector +{ +public: + ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split); + ~ServerMapSector(); + + u32 getId() const + { + return MAPSECTOR_SERVER; + } + + void setHeightmap(v2s16 hm_p, FixedHeightmap *hm); + FixedHeightmap * getHeightmap(v2s16 hm_p); + + void printHeightmaps() + { + for(s16 y=0; y<m_hm_split; y++) + for(s16 x=0; x<m_hm_split; x++) + { + std::cout<<"Sector " + <<"("<<m_pos.X<<","<<m_pos.Y<<")" + " heightmap " + "("<<x<<","<<y<<"):" + <<std::endl; + FixedHeightmap *hm = getHeightmap(v2s16(x,y)); + hm->print(); + } + } + + void setObjects(core::map<v3s16, u8> *objects) + { + m_objects = objects; + differs_from_disk = true; + } + + core::map<v3s16, u8> * getObjects() + { + differs_from_disk = true; + return m_objects; + } + + f32 getGroundHeight(v2s16 p, bool generate=false); + void setGroundHeight(v2s16 p, f32 y, bool generate=false); + + /* + These functions handle metadata. + They do not handle blocks. + */ + void serialize(std::ostream &os, u8 version); + + static ServerMapSector* deSerialize( + std::istream &is, + NodeContainer *parent, + v2s16 p2d, + Heightmap *master_hm, + core::map<v2s16, MapSector*> & sectors + ); + +private: + // Heightmap(s) for the sector + FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT]; + // Sector is split in m_hm_split^2 heightmaps. + // Value of 0 means there is no heightmap. + u16 m_hm_split; + // These are removed when they are drawn to blocks. + // - Each is drawn when generating blocks; When the last one of + // the needed blocks is being generated. + core::map<v3s16, u8> *m_objects; +}; + +class ClientMapSector : public MapSector +{ +public: + ClientMapSector(NodeContainer *parent, v2s16 pos); + ~ClientMapSector(); + + u32 getId() const + { + return MAPSECTOR_CLIENT; + } + + void deSerialize(std::istream &is); + + s16 getCorner(u16 i) + { + return m_corners[i]; + } + +private: + // The ground height of the corners is stored in here + s16 m_corners[4]; +}; + +#endif + |