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
44 #define MAPSECTOR_SERVER 0
45 #define MAPSECTOR_CLIENT 1
47 class MapSector: public NodeContainer, public Heightmappish
51 MapSector(NodeContainer *parent, v2s16 pos);
54 virtual u16 nodeContainerId() const
56 return NODECONTAINER_ID_MAPSECTOR;
59 virtual u32 getId() const = 0;
68 MapBlock * getBlockNoCreate(s16 y);
69 MapBlock * createBlankBlockNoInsert(s16 y);
70 MapBlock * createBlankBlock(s16 y);
71 //MapBlock * getBlock(s16 y, bool generate=true);
73 void insertBlock(MapBlock *block);
75 // This is used to remove a dummy from the sector while generating it.
76 // Block is only removed from internal container, not deleted.
77 void removeBlock(MapBlock *block);
80 This might not be a thread-safe depending on the day.
81 See the implementation.
83 void getBlocks(core::list<MapBlock*> &dest);
86 If all nodes in area can be accessed, returns true and
87 adds all blocks in area to blocks.
89 If all nodes in area cannot be accessed, returns false.
91 The implementation of this is quite slow
93 if blocks==NULL; it is not accessed at all.
95 bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
96 core::map<s16, MapBlock*> *blocks)
98 core::map<s16, MapBlock*> bs;
100 v3s16 p_min = getNodeBlockPos(p_min_nodes);
101 v3s16 p_max = getNodeBlockPos(p_max_nodes);
102 if(p_min.X != 0 || p_min.Z != 0
103 || p_max.X != 0 || p_max.Z != 0)
106 for(s16 y=p_min.Y; y<=p_max.Y; y++)
109 MapBlock *block = getBlockNoCreate(y);
115 catch(InvalidPositionException &e)
123 for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
124 i.atEnd()==false; i++)
126 MapBlock *block = i.getNode()->getValue();
127 s16 y = i.getNode()->getKey();
128 blocks->insert(y, block);
134 void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
135 core::map<v3s16, MapBlock*> &blocks)
137 v3s16 p_min = getNodeBlockPos(p_min_nodes);
138 v3s16 p_max = getNodeBlockPos(p_max_nodes);
140 for(s16 y=p_min.Y; y<=p_max.Y; y++)
143 MapBlock *block = getBlockNoCreate(y);
144 blocks.insert(block->getPos(), block);
146 catch(InvalidPositionException &e)
152 // virtual from NodeContainer
153 bool isValidPosition(v3s16 p)
155 v3s16 blockpos = getNodeBlockPos(p);
157 if(blockpos.X != 0 || blockpos.Z != 0)
162 blockref = getBlockNoCreate(blockpos.Y);
164 catch(InvalidPositionException &e)
172 // virtual from NodeContainer
173 MapNode getNode(v3s16 p)
175 v3s16 blockpos = getNodeBlockPos(p);
176 if(blockpos.X != 0 || blockpos.Z != 0)
177 throw InvalidPositionException
178 ("MapSector only allows Y");
180 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
181 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
183 return blockref->getNode(relpos);
185 // virtual from NodeContainer
186 void setNode(v3s16 p, MapNode & n)
188 v3s16 blockpos = getNodeBlockPos(p);
189 if(blockpos.X != 0 || blockpos.Z != 0)
190 throw InvalidPositionException
191 ("MapSector only allows Y");
193 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
194 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
195 blockref->setNode(relpos, n);
198 virtual f32 getGroundHeight(v2s16 p, bool generate=false)
200 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
202 virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
206 // When true, sector metadata is changed from the one on disk
207 // (sector metadata = all but blocks)
208 // Basically, this should be changed to true in every setter method
209 bool differs_from_disk;
211 // Counts seconds from last usage.
212 // Sector can be deleted from memory after some time of inactivity.
213 // NOTE: It has to be made very sure no other thread is accessing
214 // the sector and it doesn't remain in any cache when
220 // The pile of MapBlocks
221 core::map<s16, MapBlock*> m_blocks;
222 //JMutex m_blocks_mutex; // For public access functions
224 NodeContainer *m_parent;
225 // Position on parent (in MapBlock widths)
228 // Be sure to set this to NULL when the cached block is deleted
229 MapBlock *m_block_cache;
232 // This is used for protecting m_blocks
238 MapBlock *getBlockBuffered(s16 y);
242 class ServerMapSector : public MapSector
245 ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split);
250 return MAPSECTOR_SERVER;
253 void setHeightmap(v2s16 hm_p, FixedHeightmap *hm);
254 FixedHeightmap * getHeightmap(v2s16 hm_p);
256 void printHeightmaps()
258 for(s16 y=0; y<m_hm_split; y++)
259 for(s16 x=0; x<m_hm_split; x++)
262 <<"("<<m_pos.X<<","<<m_pos.Y<<")"
266 FixedHeightmap *hm = getHeightmap(v2s16(x,y));
271 void setObjects(core::map<v3s16, u8> *objects)
274 differs_from_disk = true;
277 core::map<v3s16, u8> * getObjects()
279 differs_from_disk = true;
283 f32 getGroundHeight(v2s16 p, bool generate=false);
284 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
287 These functions handle metadata.
288 They do not handle blocks.
290 void serialize(std::ostream &os, u8 version);
292 static ServerMapSector* deSerialize(
294 NodeContainer *parent,
296 Heightmap *master_hm,
297 core::map<v2s16, MapSector*> & sectors
301 // Heightmap(s) for the sector
302 FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT];
303 // Sector is split in m_hm_split^2 heightmaps.
304 // Value of 0 means there is no heightmap.
306 // These are removed when they are drawn to blocks.
307 // - Each is drawn when generating blocks; When the last one of
308 // the needed blocks is being generated.
309 core::map<v3s16, u8> *m_objects;
313 class ClientMapSector : public MapSector
316 ClientMapSector(NodeContainer *parent, v2s16 pos);
321 return MAPSECTOR_CLIENT;
324 void deSerialize(std::istream &is);
332 // The ground height of the corners is stored in here