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
23 #define SECTOR_OBJECT_RAVINE 3
25 #define MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT 4
27 #define MAPSECTOR_SERVER 0
28 #define MAPSECTOR_CLIENT 1
30 class MapSector: public NodeContainer, public Heightmappish
34 MapSector(NodeContainer *parent, v2s16 pos);
37 virtual u16 nodeContainerId() const
39 return NODECONTAINER_ID_MAPSECTOR;
42 virtual u32 getId() const = 0;
51 MapBlock * getBlockNoCreate(s16 y);
52 MapBlock * createBlankBlockNoInsert(s16 y);
53 MapBlock * createBlankBlock(s16 y);
54 //MapBlock * getBlock(s16 y, bool generate=true);
56 void insertBlock(MapBlock *block);
58 // This is used to remove a dummy from the sector while generating it.
59 // Block is only removed from internal container, not deleted.
60 void removeBlock(MapBlock *block);
63 This might not be a thread-safe depending on the day.
64 See the implementation.
66 void getBlocks(core::list<MapBlock*> &dest);
69 If all nodes in area can be accessed, returns true and
70 adds all blocks in area to blocks.
72 If all nodes in area cannot be accessed, returns false.
74 The implementation of this is quite slow
76 if blocks==NULL; it is not accessed at all.
78 bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
79 core::map<s16, MapBlock*> *blocks)
81 core::map<s16, MapBlock*> bs;
83 v3s16 p_min = getNodeBlockPos(p_min_nodes);
84 v3s16 p_max = getNodeBlockPos(p_max_nodes);
85 if(p_min.X != 0 || p_min.Z != 0
86 || p_max.X != 0 || p_max.Z != 0)
89 for(s16 y=p_min.Y; y<=p_max.Y; y++)
92 MapBlock *block = getBlockNoCreate(y);
98 catch(InvalidPositionException &e)
106 for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
107 i.atEnd()==false; i++)
109 MapBlock *block = i.getNode()->getValue();
110 s16 y = i.getNode()->getKey();
111 blocks->insert(y, block);
117 void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
118 core::map<v3s16, MapBlock*> &blocks)
120 v3s16 p_min = getNodeBlockPos(p_min_nodes);
121 v3s16 p_max = getNodeBlockPos(p_max_nodes);
123 for(s16 y=p_min.Y; y<=p_max.Y; y++)
126 MapBlock *block = getBlockNoCreate(y);
127 blocks.insert(block->getPos(), block);
129 catch(InvalidPositionException &e)
135 // virtual from NodeContainer
136 bool isValidPosition(v3s16 p)
138 v3s16 blockpos = getNodeBlockPos(p);
140 if(blockpos.X != 0 || blockpos.Z != 0)
145 blockref = getBlockNoCreate(blockpos.Y);
147 catch(InvalidPositionException &e)
155 // virtual from NodeContainer
156 MapNode getNode(v3s16 p)
158 v3s16 blockpos = getNodeBlockPos(p);
159 if(blockpos.X != 0 || blockpos.Z != 0)
160 throw InvalidPositionException
161 ("MapSector only allows Y");
163 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
164 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
166 return blockref->getNode(relpos);
168 // virtual from NodeContainer
169 void setNode(v3s16 p, MapNode & n)
171 v3s16 blockpos = getNodeBlockPos(p);
172 if(blockpos.X != 0 || blockpos.Z != 0)
173 throw InvalidPositionException
174 ("MapSector only allows Y");
176 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
177 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
178 blockref->setNode(relpos, n);
181 virtual f32 getGroundHeight(v2s16 p, bool generate=false)
183 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
185 virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
189 // When true, sector metadata is changed from the one on disk
190 // (sector metadata = all but blocks)
191 // Basically, this should be changed to true in every setter method
192 bool differs_from_disk;
194 // Counts seconds from last usage.
195 // Sector can be deleted from memory after some time of inactivity.
196 // NOTE: It has to be made very sure no other thread is accessing
197 // the sector and it doesn't remain in any cache when
203 // The pile of MapBlocks
204 core::map<s16, MapBlock*> m_blocks;
205 //JMutex m_blocks_mutex; // For public access functions
207 NodeContainer *m_parent;
208 // Position on parent (in MapBlock widths)
211 // Be sure to set this to NULL when the cached block is deleted
212 MapBlock *m_block_cache;
215 // This is used for protecting m_blocks
221 MapBlock *getBlockBuffered(s16 y);
225 class ServerMapSector : public MapSector
228 ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split);
233 return MAPSECTOR_SERVER;
236 void setHeightmap(v2s16 hm_p, FixedHeightmap *hm);
237 FixedHeightmap * getHeightmap(v2s16 hm_p);
239 void printHeightmaps()
241 for(s16 y=0; y<m_hm_split; y++)
242 for(s16 x=0; x<m_hm_split; x++)
245 <<"("<<m_pos.X<<","<<m_pos.Y<<")"
249 FixedHeightmap *hm = getHeightmap(v2s16(x,y));
254 void setObjects(core::map<v3s16, u8> *objects)
257 differs_from_disk = true;
260 core::map<v3s16, u8> * getObjects()
262 differs_from_disk = true;
266 f32 getGroundHeight(v2s16 p, bool generate=false);
267 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
270 These functions handle metadata.
271 They do not handle blocks.
273 void serialize(std::ostream &os, u8 version);
275 static ServerMapSector* deSerialize(
277 NodeContainer *parent,
279 Heightmap *master_hm,
280 core::map<v2s16, MapSector*> & sectors
284 // Heightmap(s) for the sector
285 FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT];
286 // Sector is split in m_hm_split^2 heightmaps.
287 // Value of 0 means there is no heightmap.
289 // These are removed when they are drawn to blocks.
290 // - Each is drawn when generating blocks; When the last one of
291 // the needed blocks is being generated.
292 core::map<v3s16, u8> *m_objects;
295 class ClientMapSector : public MapSector
298 ClientMapSector(NodeContainer *parent, v2s16 pos);
303 return MAPSECTOR_CLIENT;
306 void deSerialize(std::istream &is);
314 // The ground height of the corners is stored in here