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.
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
24 #ifndef MAPSECTOR_HEADER
25 #define MAPSECTOR_HEADER
28 #include "common_irrlicht.h"
30 #include "heightmap.h"
31 #include "exceptions.h"
34 This is an Y-wise stack of MapBlocks.
37 #define SECTOR_OBJECT_TEST 0
38 #define SECTOR_OBJECT_TREE_1 1
39 #define SECTOR_OBJECT_BUSH_1 2
40 #define SECTOR_OBJECT_RAVINE 3
42 //#define MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT 4
43 #define MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT \
44 (SECTOR_HEIGHTMAP_SPLIT * SECTOR_HEIGHTMAP_SPLIT)
46 #define MAPSECTOR_SERVER 0
47 #define MAPSECTOR_CLIENT 1
49 class MapSector: public NodeContainer, public Heightmappish
53 MapSector(NodeContainer *parent, v2s16 pos);
56 virtual u16 nodeContainerId() const
58 return NODECONTAINER_ID_MAPSECTOR;
61 virtual u32 getId() const = 0;
70 MapBlock * getBlockNoCreateNoEx(s16 y);
71 MapBlock * getBlockNoCreate(s16 y);
72 MapBlock * createBlankBlockNoInsert(s16 y);
73 MapBlock * createBlankBlock(s16 y);
74 //MapBlock * getBlock(s16 y, bool generate=true);
76 void insertBlock(MapBlock *block);
78 // This is used to remove a dummy from the sector while generating it.
79 // Block is only removed from internal container, not deleted.
80 void removeBlock(MapBlock *block);
83 This might not be a thread-safe depending on the day.
84 See the implementation.
86 void getBlocks(core::list<MapBlock*> &dest);
89 If all nodes in area can be accessed, returns true and
90 adds all blocks in area to blocks.
92 If all nodes in area cannot be accessed, returns false.
94 The implementation of this is quite slow
96 if blocks==NULL; it is not accessed at all.
98 bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
99 core::map<s16, MapBlock*> *blocks)
101 core::map<s16, MapBlock*> bs;
103 v3s16 p_min = getNodeBlockPos(p_min_nodes);
104 v3s16 p_max = getNodeBlockPos(p_max_nodes);
105 if(p_min.X != 0 || p_min.Z != 0
106 || p_max.X != 0 || p_max.Z != 0)
109 for(s16 y=p_min.Y; y<=p_max.Y; y++)
112 MapBlock *block = getBlockNoCreate(y);
118 catch(InvalidPositionException &e)
126 for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
127 i.atEnd()==false; i++)
129 MapBlock *block = i.getNode()->getValue();
130 s16 y = i.getNode()->getKey();
131 blocks->insert(y, block);
137 void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
138 core::map<v3s16, MapBlock*> &blocks)
140 v3s16 p_min = getNodeBlockPos(p_min_nodes);
141 v3s16 p_max = getNodeBlockPos(p_max_nodes);
143 for(s16 y=p_min.Y; y<=p_max.Y; y++)
146 MapBlock *block = getBlockNoCreate(y);
147 blocks.insert(block->getPos(), block);
149 catch(InvalidPositionException &e)
155 // virtual from NodeContainer
156 bool isValidPosition(v3s16 p)
158 v3s16 blockpos = getNodeBlockPos(p);
160 if(blockpos.X != 0 || blockpos.Z != 0)
165 blockref = getBlockNoCreate(blockpos.Y);
167 catch(InvalidPositionException &e)
175 // virtual from NodeContainer
176 MapNode getNode(v3s16 p)
178 v3s16 blockpos = getNodeBlockPos(p);
179 if(blockpos.X != 0 || blockpos.Z != 0)
180 throw InvalidPositionException
181 ("MapSector only allows Y");
183 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
184 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
186 return blockref->getNode(relpos);
188 // virtual from NodeContainer
189 void setNode(v3s16 p, MapNode & n)
191 v3s16 blockpos = getNodeBlockPos(p);
192 if(blockpos.X != 0 || blockpos.Z != 0)
193 throw InvalidPositionException
194 ("MapSector only allows Y");
196 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
197 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
198 blockref->setNode(relpos, n);
201 virtual f32 getGroundHeight(v2s16 p, bool generate=false)
203 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
205 virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
209 // When true, sector metadata is changed from the one on disk
210 // (sector metadata = all but blocks)
211 // Basically, this should be changed to true in every setter method
212 bool differs_from_disk;
214 // Counts seconds from last usage.
215 // Sector can be deleted from memory after some time of inactivity.
216 // NOTE: It has to be made very sure no other thread is accessing
217 // the sector and it doesn't remain in any cache when
223 // The pile of MapBlocks
224 core::map<s16, MapBlock*> m_blocks;
225 //JMutex m_blocks_mutex; // For public access functions
227 NodeContainer *m_parent;
228 // Position on parent (in MapBlock widths)
231 // Be sure to set this to NULL when the cached block is deleted
232 MapBlock *m_block_cache;
235 // This is used for protecting m_blocks
241 MapBlock *getBlockBuffered(s16 y);
245 class ServerMapSector : public MapSector
248 ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split);
253 return MAPSECTOR_SERVER;
256 void setHeightmap(v2s16 hm_p, FixedHeightmap *hm);
257 FixedHeightmap * getHeightmap(v2s16 hm_p);
259 void printHeightmaps()
261 for(s16 y=0; y<m_hm_split; y++)
262 for(s16 x=0; x<m_hm_split; x++)
265 <<"("<<m_pos.X<<","<<m_pos.Y<<")"
269 FixedHeightmap *hm = getHeightmap(v2s16(x,y));
274 void setObjects(core::map<v3s16, u8> *objects)
277 differs_from_disk = true;
280 core::map<v3s16, u8> * getObjects()
282 differs_from_disk = true;
286 f32 getGroundHeight(v2s16 p, bool generate=false);
287 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
290 These functions handle metadata.
291 They do not handle blocks.
293 void serialize(std::ostream &os, u8 version);
295 static ServerMapSector* deSerialize(
297 NodeContainer *parent,
299 Heightmap *master_hm,
300 core::map<v2s16, MapSector*> & sectors
304 // Heightmap(s) for the sector
305 FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT];
306 // Sector is split in m_hm_split^2 heightmaps.
307 // Value of 0 means there is no heightmap.
309 // These are removed when they are drawn to blocks.
310 // - Each is drawn when generating blocks; When the last one of
311 // the needed blocks is being generated.
312 core::map<v3s16, u8> *m_objects;
316 class ClientMapSector : public MapSector
319 ClientMapSector(NodeContainer *parent, v2s16 pos);
324 return MAPSECTOR_CLIENT;
327 void deSerialize(std::istream &is);
335 // The ground height of the corners is stored in here