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 * getBlockNoCreate(s16 y);
71 MapBlock * createBlankBlockNoInsert(s16 y);
72 MapBlock * createBlankBlock(s16 y);
73 //MapBlock * getBlock(s16 y, bool generate=true);
75 void insertBlock(MapBlock *block);
77 // This is used to remove a dummy from the sector while generating it.
78 // Block is only removed from internal container, not deleted.
79 void removeBlock(MapBlock *block);
82 This might not be a thread-safe depending on the day.
83 See the implementation.
85 void getBlocks(core::list<MapBlock*> &dest);
88 If all nodes in area can be accessed, returns true and
89 adds all blocks in area to blocks.
91 If all nodes in area cannot be accessed, returns false.
93 The implementation of this is quite slow
95 if blocks==NULL; it is not accessed at all.
97 bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
98 core::map<s16, MapBlock*> *blocks)
100 core::map<s16, MapBlock*> bs;
102 v3s16 p_min = getNodeBlockPos(p_min_nodes);
103 v3s16 p_max = getNodeBlockPos(p_max_nodes);
104 if(p_min.X != 0 || p_min.Z != 0
105 || p_max.X != 0 || p_max.Z != 0)
108 for(s16 y=p_min.Y; y<=p_max.Y; y++)
111 MapBlock *block = getBlockNoCreate(y);
117 catch(InvalidPositionException &e)
125 for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
126 i.atEnd()==false; i++)
128 MapBlock *block = i.getNode()->getValue();
129 s16 y = i.getNode()->getKey();
130 blocks->insert(y, block);
136 void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
137 core::map<v3s16, MapBlock*> &blocks)
139 v3s16 p_min = getNodeBlockPos(p_min_nodes);
140 v3s16 p_max = getNodeBlockPos(p_max_nodes);
142 for(s16 y=p_min.Y; y<=p_max.Y; y++)
145 MapBlock *block = getBlockNoCreate(y);
146 blocks.insert(block->getPos(), block);
148 catch(InvalidPositionException &e)
154 // virtual from NodeContainer
155 bool isValidPosition(v3s16 p)
157 v3s16 blockpos = getNodeBlockPos(p);
159 if(blockpos.X != 0 || blockpos.Z != 0)
164 blockref = getBlockNoCreate(blockpos.Y);
166 catch(InvalidPositionException &e)
174 // virtual from NodeContainer
175 MapNode getNode(v3s16 p)
177 v3s16 blockpos = getNodeBlockPos(p);
178 if(blockpos.X != 0 || blockpos.Z != 0)
179 throw InvalidPositionException
180 ("MapSector only allows Y");
182 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
183 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
185 return blockref->getNode(relpos);
187 // virtual from NodeContainer
188 void setNode(v3s16 p, MapNode & n)
190 v3s16 blockpos = getNodeBlockPos(p);
191 if(blockpos.X != 0 || blockpos.Z != 0)
192 throw InvalidPositionException
193 ("MapSector only allows Y");
195 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
196 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
197 blockref->setNode(relpos, n);
200 virtual f32 getGroundHeight(v2s16 p, bool generate=false)
202 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
204 virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
208 // When true, sector metadata is changed from the one on disk
209 // (sector metadata = all but blocks)
210 // Basically, this should be changed to true in every setter method
211 bool differs_from_disk;
213 // Counts seconds from last usage.
214 // Sector can be deleted from memory after some time of inactivity.
215 // NOTE: It has to be made very sure no other thread is accessing
216 // the sector and it doesn't remain in any cache when
222 // The pile of MapBlocks
223 core::map<s16, MapBlock*> m_blocks;
224 //JMutex m_blocks_mutex; // For public access functions
226 NodeContainer *m_parent;
227 // Position on parent (in MapBlock widths)
230 // Be sure to set this to NULL when the cached block is deleted
231 MapBlock *m_block_cache;
234 // This is used for protecting m_blocks
240 MapBlock *getBlockBuffered(s16 y);
244 class ServerMapSector : public MapSector
247 ServerMapSector(NodeContainer *parent, v2s16 pos, u16 hm_split);
252 return MAPSECTOR_SERVER;
255 void setHeightmap(v2s16 hm_p, FixedHeightmap *hm);
256 FixedHeightmap * getHeightmap(v2s16 hm_p);
258 void printHeightmaps()
260 for(s16 y=0; y<m_hm_split; y++)
261 for(s16 x=0; x<m_hm_split; x++)
264 <<"("<<m_pos.X<<","<<m_pos.Y<<")"
268 FixedHeightmap *hm = getHeightmap(v2s16(x,y));
273 void setObjects(core::map<v3s16, u8> *objects)
276 differs_from_disk = true;
279 core::map<v3s16, u8> * getObjects()
281 differs_from_disk = true;
285 f32 getGroundHeight(v2s16 p, bool generate=false);
286 void setGroundHeight(v2s16 p, f32 y, bool generate=false);
289 These functions handle metadata.
290 They do not handle blocks.
292 void serialize(std::ostream &os, u8 version);
294 static ServerMapSector* deSerialize(
296 NodeContainer *parent,
298 Heightmap *master_hm,
299 core::map<v2s16, MapSector*> & sectors
303 // Heightmap(s) for the sector
304 FixedHeightmap *m_heightmaps[MAPSECTOR_FIXEDHEIGHTMAPS_MAXCOUNT];
305 // Sector is split in m_hm_split^2 heightmaps.
306 // Value of 0 means there is no heightmap.
308 // These are removed when they are drawn to blocks.
309 // - Each is drawn when generating blocks; When the last one of
310 // the needed blocks is being generated.
311 core::map<v3s16, u8> *m_objects;
315 class ClientMapSector : public MapSector
318 ClientMapSector(NodeContainer *parent, v2s16 pos);
323 return MAPSECTOR_CLIENT;
326 void deSerialize(std::istream &is);
334 // The ground height of the corners is stored in here