2 (c) 2010 Perttu Ahola <celeron55@gmail.com>
5 #ifndef MAPSECTOR_HEADER
6 #define MAPSECTOR_HEADER
9 #include "common_irrlicht.h"
11 #include "heightmap.h"
12 #include "exceptions.h"
15 This is an Y-wise stack of MapBlocks.
18 #define WATER_LEVEL (-5)
20 #define SECTOR_OBJECT_TEST 0
21 #define SECTOR_OBJECT_TREE_1 1
22 #define SECTOR_OBJECT_BUSH_1 2
24 #define MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT 4
26 #define MAPSECTOR_SERVER 0
27 #define MAPSECTOR_CLIENT 1
29 class MapSector: public NodeContainer, public Heightmappish
33 MapSector(NodeContainer *parent, v2s16 pos);
36 virtual u16 nodeContainerId() const
38 return NODECONTAINER_ID_MAPSECTOR;
41 virtual u32 getId() const = 0;
50 MapBlock * getBlockNoCreate(s16 y);
51 MapBlock * createBlankBlockNoInsert(s16 y);
52 MapBlock * createBlankBlock(s16 y);
53 //MapBlock * getBlock(s16 y, bool generate=true);
55 void insertBlock(MapBlock *block);
57 // This is used to remove a dummy from the sector while generating it.
58 // Block is only removed from internal container, not deleted.
59 void removeBlock(MapBlock *block);
62 This might not be a thread-safe depending on the day.
63 See the implementation.
65 void getBlocks(core::list<MapBlock*> &dest);
68 If all nodes in area can be accessed, returns true and
69 adds all blocks in area to blocks.
71 If all nodes in area cannot be accessed, returns false.
73 The implementation of this is quite slow
75 if blocks==NULL; it is not accessed at all.
77 bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
78 core::map<s16, MapBlock*> *blocks)
80 core::map<s16, MapBlock*> bs;
82 v3s16 p_min = getNodeBlockPos(p_min_nodes);
83 v3s16 p_max = getNodeBlockPos(p_max_nodes);
84 if(p_min.X != 0 || p_min.Z != 0
85 || p_max.X != 0 || p_max.Z != 0)
88 for(s16 y=p_min.Y; y<=p_max.Y; y++)
91 MapBlock *block = getBlockNoCreate(y);
97 catch(InvalidPositionException &e)
105 for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
106 i.atEnd()==false; i++)
108 MapBlock *block = i.getNode()->getValue();
109 s16 y = i.getNode()->getKey();
110 blocks->insert(y, block);
116 void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
117 core::map<v3s16, MapBlock*> &blocks)
119 v3s16 p_min = getNodeBlockPos(p_min_nodes);
120 v3s16 p_max = getNodeBlockPos(p_max_nodes);
122 for(s16 y=p_min.Y; y<=p_max.Y; y++)
125 MapBlock *block = getBlockNoCreate(y);
126 blocks.insert(block->getPos(), block);
128 catch(InvalidPositionException &e)
134 // virtual from NodeContainer
135 bool isValidPosition(v3s16 p)
137 v3s16 blockpos = getNodeBlockPos(p);
139 if(blockpos.X != 0 || blockpos.Z != 0)
144 blockref = getBlockNoCreate(blockpos.Y);
146 catch(InvalidPositionException &e)
154 // virtual from NodeContainer
155 MapNode getNode(v3s16 p)
157 v3s16 blockpos = getNodeBlockPos(p);
158 if(blockpos.X != 0 || blockpos.Z != 0)
159 throw InvalidPositionException
160 ("MapSector only allows Y");
162 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
163 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
165 return blockref->getNode(relpos);
167 // virtual from NodeContainer
168 void setNode(v3s16 p, MapNode & n)
170 v3s16 blockpos = getNodeBlockPos(p);
171 if(blockpos.X != 0 || blockpos.Z != 0)
172 throw InvalidPositionException
173 ("MapSector only allows Y");
175 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
176 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
177 blockref->setNode(relpos, n);
180 virtual f32 getGroundHeight(v2s16 p, bool generate=false)
182 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
184 virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
188 // When true, sector metadata is changed from the one on disk
189 // (sector metadata = all but blocks)
190 // Basically, this should be changed to true in every setter method
191 bool differs_from_disk;
193 // Counts seconds from last usage.
194 // Sector can be deleted from memory after some time of inactivity.
195 // NOTE: It has to be made very sure no other thread is accessing
196 // the sector and it doesn't remain in any cache when
202 // The pile of MapBlocks
203 core::map<s16, MapBlock*> m_blocks;
204 //JMutex m_blocks_mutex; // For public access functions
206 NodeContainer *m_parent;
207 // Position on parent (in MapBlock widths)
210 // Be sure to set this to NULL when the cached block is deleted
211 MapBlock *m_block_cache;
214 // This is used for protecting m_blocks
220 MapBlock *getBlockBuffered(s16 y);
224 class ServerMapSector : public MapSector
227 ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split);
232 return MAPSECTOR_SERVER;
235 void setHeightmap(v2s16 hm_p, FixedHeightmap *hm);
236 FixedHeightmap * getHeightmap(v2s16 hm_p);
238 void printHeightmaps()
240 for(s16 y=0; y<m_hm_split; y++)
241 for(s16 x=0; x<m_hm_split; x++)
244 <<"("<<m_pos.X<<","<<m_pos.Y<<")"
248 FixedHeightmap *hm = getHeightmap(v2s16(x,y));
253 void setObjects(core::map<v3s16, u8> *objects)
256 differs_from_disk = true;
259 core::map<v3s16, u8> * getObjects()
261 differs_from_disk = true;
265 f32 getGroundHeight(v2s16 p, bool generate=false);
266 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
269 These functions handle metadata.
270 They do not handle blocks.
272 void serialize(std::ostream &os, u8 version);
274 static ServerMapSector* deSerialize(
276 NodeContainer *parent,
278 Heightmap *master_hm,
279 core::map<v2s16, MapSector*> & sectors
283 // Heightmap(s) for the sector
284 FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT];
285 // Sector is split in m_hm_split^2 heightmaps.
286 // Value of 0 means there is no heightmap.
288 // These are removed when they are drawn to blocks.
289 // - Each is drawn when generating blocks; When the last one of
290 // the needed blocks is being generated.
291 core::map<v3s16, u8> *m_objects;
294 class ClientMapSector : public MapSector
297 ClientMapSector(NodeContainer *parent, v2s16 pos);
302 return MAPSECTOR_CLIENT;
305 void deSerialize(std::istream &is);
313 // The ground height of the corners is stored in here