]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapsector.h
merged CiaranG's stuff again: auto-admin powers to local user, DSTACK macro -Wformat...
[dragonfireclient.git] / src / mapsector.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #ifndef MAPSECTOR_HEADER
25 #define MAPSECTOR_HEADER
26
27 #include <jmutex.h>
28 #include "common_irrlicht.h"
29 #include "mapblock.h"
30 //#include "heightmap.h"
31 #include "exceptions.h"
32
33 /*
34         This is an Y-wise stack of MapBlocks.
35 */
36
37 #define MAPSECTOR_SERVER 0
38 #define MAPSECTOR_CLIENT 1
39
40 class MapSector: public NodeContainer
41 {
42 public:
43         
44         MapSector(NodeContainer *parent, v2s16 pos);
45         virtual ~MapSector();
46
47         virtual u16 nodeContainerId() const
48         {
49                 return NODECONTAINER_ID_MAPSECTOR;
50         }
51
52         virtual u32 getId() const = 0;
53
54         void deleteBlocks();
55
56         v2s16 getPos()
57         {
58                 return m_pos;
59         }
60
61         MapBlock * getBlockNoCreateNoEx(s16 y);
62         MapBlock * getBlockNoCreate(s16 y);
63         MapBlock * createBlankBlockNoInsert(s16 y);
64         MapBlock * createBlankBlock(s16 y);
65         //MapBlock * getBlock(s16 y, bool generate=true);
66
67         void insertBlock(MapBlock *block);
68         
69         // This is used to remove a dummy from the sector while generating it.
70         // Block is only removed from internal container, not deleted.
71         void removeBlock(MapBlock *block);
72         
73         /*
74                 This might not be a thread-safe depending on the day.
75                 See the implementation.
76         */
77         void getBlocks(core::list<MapBlock*> &dest);
78         
79         /*
80                 If all nodes in area can be accessed, returns true and
81                 adds all blocks in area to blocks.
82
83                 If all nodes in area cannot be accessed, returns false.
84
85                 The implementation of this is quite slow
86
87                 if blocks==NULL; it is not accessed at all.
88         */
89         bool isValidArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
90                         core::map<s16, MapBlock*> *blocks)
91         {
92                 core::map<s16, MapBlock*> bs;
93                 
94                 v3s16 p_min = getNodeBlockPos(p_min_nodes);
95                 v3s16 p_max = getNodeBlockPos(p_max_nodes);
96                 if(p_min.X != 0 || p_min.Z != 0
97                                 || p_max.X != 0 || p_max.Z != 0)
98                         return false;
99                 v3s16 y;
100                 for(s16 y=p_min.Y; y<=p_max.Y; y++)
101                 {
102                         try{
103                                 MapBlock *block = getBlockNoCreate(y);
104                                 if(block->isDummy())
105                                         return false;
106                                 if(blocks!=NULL)
107                                         bs[y] = block;
108                         }
109                         catch(InvalidPositionException &e)
110                         {
111                                 return false;
112                         }
113                 }
114
115                 if(blocks!=NULL)
116                 {
117                         for(core::map<s16, MapBlock*>::Iterator i=bs.getIterator();
118                                         i.atEnd()==false; i++)
119                         {
120                                 MapBlock *block = i.getNode()->getValue();
121                                 s16 y = i.getNode()->getKey();
122                                 blocks->insert(y, block);
123                         }
124                 }
125                 return true;
126         }
127
128         void getBlocksInArea(v3s16 p_min_nodes, v3s16 p_max_nodes,
129                         core::map<v3s16, MapBlock*> &blocks)
130         {
131                 v3s16 p_min = getNodeBlockPos(p_min_nodes);
132                 v3s16 p_max = getNodeBlockPos(p_max_nodes);
133                 v3s16 y;
134                 for(s16 y=p_min.Y; y<=p_max.Y; y++)
135                 {
136                         try{
137                                 MapBlock *block = getBlockNoCreate(y);
138                                 blocks.insert(block->getPos(), block);
139                         }
140                         catch(InvalidPositionException &e)
141                         {
142                         }
143                 }
144         }
145         
146         // virtual from NodeContainer
147         bool isValidPosition(v3s16 p)
148         {
149                 v3s16 blockpos = getNodeBlockPos(p);
150
151                 if(blockpos.X != 0 || blockpos.Z != 0)
152                         return false;
153
154                 MapBlock *blockref;
155                 try{
156                         blockref = getBlockNoCreate(blockpos.Y);
157                 }
158                 catch(InvalidPositionException &e)
159                 {
160                         return false;
161                 }
162
163                 return true;
164         }
165
166         // virtual from NodeContainer
167         MapNode getNode(v3s16 p)
168         {
169                 v3s16 blockpos = getNodeBlockPos(p);
170                 if(blockpos.X != 0 || blockpos.Z != 0)
171                         throw InvalidPositionException
172                                 ("MapSector only allows Y");
173
174                 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
175                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
176
177                 return blockref->getNode(relpos);
178         }
179         // virtual from NodeContainer
180         void setNode(v3s16 p, MapNode & n)
181         {
182                 v3s16 blockpos = getNodeBlockPos(p);
183                 if(blockpos.X != 0 || blockpos.Z != 0)
184                         throw InvalidPositionException
185                                 ("MapSector only allows Y");
186
187                 MapBlock * blockref = getBlockNoCreate(blockpos.Y);
188                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
189                 blockref->setNode(relpos, n);
190         }
191
192         // DEPRECATED?
193         virtual f32 getGroundHeight(v2s16 p, bool generate=false)
194         {
195                 return GROUNDHEIGHT_NOTFOUND_SETVALUE;
196         }
197         virtual void setGroundHeight(v2s16 p, f32 y, bool generate=false)
198         {
199         }
200         
201         // When true, sector metadata is changed from the one on disk
202         // (sector metadata = all but blocks)
203         // Basically, this should be changed to true in every setter method
204         bool differs_from_disk;
205
206         // Counts seconds from last usage.
207         // Sector can be deleted from memory after some time of inactivity.
208         // NOTE: It has to be made very sure no other thread is accessing
209         //       the sector and it doesn't remain in any cache when
210         //       deleting it.
211         float usage_timer;
212
213 protected:
214         
215         // The pile of MapBlocks
216         core::map<s16, MapBlock*> m_blocks;
217         //JMutex m_blocks_mutex; // For public access functions
218
219         NodeContainer *m_parent;
220         // Position on parent (in MapBlock widths)
221         v2s16 m_pos;
222
223         // Be sure to set this to NULL when the cached block is deleted 
224         MapBlock *m_block_cache;
225         s16 m_block_cache_y;
226         
227         // This is used for protecting m_blocks
228         JMutex m_mutex;
229         
230         /*
231                 Private methods
232         */
233         MapBlock *getBlockBuffered(s16 y);
234
235 };
236
237 class ServerMapSector : public MapSector
238 {
239 public:
240         ServerMapSector(NodeContainer *parent, v2s16 pos);
241         ~ServerMapSector();
242         
243         u32 getId() const
244         {
245                 return MAPSECTOR_SERVER;
246         }
247         
248         // DEPRECATED?
249         f32 getGroundHeight(v2s16 p, bool generate=false);
250         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
251
252         /*
253                 These functions handle metadata.
254                 They do not handle blocks.
255         */
256         void serialize(std::ostream &os, u8 version);
257         
258         static ServerMapSector* deSerialize(
259                         std::istream &is,
260                         NodeContainer *parent,
261                         v2s16 p2d,
262                         core::map<v2s16, MapSector*> & sectors
263                 );
264                 
265 private:
266 };
267
268 #ifndef SERVER
269 class ClientMapSector : public MapSector
270 {
271 public:
272         ClientMapSector(NodeContainer *parent, v2s16 pos);
273         ~ClientMapSector();
274         
275         u32 getId() const
276         {
277                 return MAPSECTOR_CLIENT;
278         }
279
280         void deSerialize(std::istream &is);
281
282         /*s16 getCorner(u16 i)
283         {
284                 return m_corners[i];
285         }*/
286                 
287 private:
288         // The ground height of the corners is stored in here
289         //s16 m_corners[4];
290 };
291 #endif
292         
293 #endif
294