mapgen stuff
[oweals/minetest.git] / src / mapsector.cpp
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 #include "mapsector.h"
21 #include "jmutexautolock.h"
22 #include "client.h"
23 #include "exceptions.h"
24
25 MapSector::MapSector(NodeContainer *parent, v2s16 pos):
26                 differs_from_disk(true),
27                 usage_timer(0.0),
28                 m_parent(parent),
29                 m_pos(pos),
30                 m_block_cache(NULL)
31 {
32         m_mutex.Init();
33         assert(m_mutex.IsInitialized());
34 }
35
36 MapSector::~MapSector()
37 {
38         deleteBlocks();
39 }
40
41 void MapSector::deleteBlocks()
42 {
43         JMutexAutoLock lock(m_mutex);
44
45         // Clear cache
46         m_block_cache = NULL;
47
48         // Delete all
49         core::map<s16, MapBlock*>::Iterator i = m_blocks.getIterator();
50         for(; i.atEnd() == false; i++)
51         {
52                 delete i.getNode()->getValue();
53         }
54
55         // Clear container
56         m_blocks.clear();
57 }
58
59 MapBlock * MapSector::getBlockBuffered(s16 y)
60 {
61         MapBlock *block;
62
63         if(m_block_cache != NULL && y == m_block_cache_y){
64                 return m_block_cache;
65         }
66         
67         // If block doesn't exist, return NULL
68         core::map<s16, MapBlock*>::Node *n = m_blocks.find(y);
69         if(n == NULL)
70         {
71                 block = NULL;
72         }
73         // If block exists, return it
74         else{
75                 block = n->getValue();
76         }
77         
78         // Cache the last result
79         m_block_cache_y = y;
80         m_block_cache = block;
81         
82         return block;
83 }
84
85 MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
86 {
87         JMutexAutoLock lock(m_mutex);
88         
89         return getBlockBuffered(y);
90 }
91
92 MapBlock * MapSector::getBlockNoCreate(s16 y)
93 {
94         MapBlock *block = getBlockNoCreateNoEx(y);
95
96         if(block == NULL)
97                 throw InvalidPositionException();
98         
99         return block;
100 }
101
102 MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
103 {
104         // There should not be a block at this position
105         if(getBlockBuffered(y) != NULL)
106                 throw AlreadyExistsException("Block already exists");
107
108         v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
109         
110         MapBlock *block = new MapBlock(m_parent, blockpos_map);
111         
112         return block;
113 }
114
115 MapBlock * MapSector::createBlankBlock(s16 y)
116 {
117         JMutexAutoLock lock(m_mutex);
118         
119         MapBlock *block = createBlankBlockNoInsert(y);
120         
121         m_blocks.insert(y, block);
122
123         return block;
124 }
125
126 void MapSector::insertBlock(MapBlock *block)
127 {
128         s16 block_y = block->getPos().Y;
129
130         {
131                 JMutexAutoLock lock(m_mutex);
132
133                 MapBlock *block2 = getBlockBuffered(block_y);
134                 if(block2 != NULL){
135                         throw AlreadyExistsException("Block already exists");
136                 }
137
138                 v2s16 p2d(block->getPos().X, block->getPos().Z);
139                 assert(p2d == m_pos);
140                 
141                 // Insert into container
142                 m_blocks.insert(block_y, block);
143         }
144 }
145
146 void MapSector::removeBlock(MapBlock *block)
147 {
148         s16 block_y = block->getPos().Y;
149
150         JMutexAutoLock lock(m_mutex);
151         
152         // Clear from cache
153         m_block_cache = NULL;
154         
155         // Remove from container
156         m_blocks.remove(block_y);
157 }
158
159 void MapSector::getBlocks(core::list<MapBlock*> &dest)
160 {
161         JMutexAutoLock lock(m_mutex);
162
163         core::list<MapBlock*> ref_list;
164
165         core::map<s16, MapBlock*>::Iterator bi;
166
167         bi = m_blocks.getIterator();
168         for(; bi.atEnd() == false; bi++)
169         {
170                 MapBlock *b = bi.getNode()->getValue();
171                 dest.push_back(b);
172         }
173 }
174
175 /*
176         ServerMapSector
177 */
178
179 ServerMapSector::ServerMapSector(NodeContainer *parent, v2s16 pos):
180                 MapSector(parent, pos)
181 {
182 }
183
184 ServerMapSector::~ServerMapSector()
185 {
186 }
187
188 f32 ServerMapSector::getGroundHeight(v2s16 p, bool generate)
189 {
190         return GROUNDHEIGHT_NOTFOUND_SETVALUE;
191 }
192
193 void ServerMapSector::setGroundHeight(v2s16 p, f32 y, bool generate)
194 {
195 }
196
197 void ServerMapSector::serialize(std::ostream &os, u8 version)
198 {
199         if(!ser_ver_supported(version))
200                 throw VersionMismatchException("ERROR: MapSector format not supported");
201         
202         /*
203                 [0] u8 serialization version
204                 + heightmap data
205         */
206         
207         // Server has both of these, no need to support not having them.
208         //assert(m_objects != NULL);
209
210         // Write version
211         os.write((char*)&version, 1);
212         
213         /*
214                 Add stuff here, if needed
215         */
216
217 }
218
219 ServerMapSector* ServerMapSector::deSerialize(
220                 std::istream &is,
221                 NodeContainer *parent,
222                 v2s16 p2d,
223                 core::map<v2s16, MapSector*> & sectors
224         )
225 {
226         /*
227                 [0] u8 serialization version
228                 + heightmap data
229         */
230
231         /*
232                 Read stuff
233         */
234         
235         // Read version
236         u8 version = SER_FMT_VER_INVALID;
237         is.read((char*)&version, 1);
238         
239         if(!ser_ver_supported(version))
240                 throw VersionMismatchException("ERROR: MapSector format not supported");
241         
242         /*
243                 Add necessary reading stuff here
244         */
245         
246         /*
247                 Get or create sector
248         */
249
250         ServerMapSector *sector = NULL;
251
252         core::map<v2s16, MapSector*>::Node *n = sectors.find(p2d);
253
254         if(n != NULL)
255         {
256                 dstream<<"WARNING: deSerializing existent sectors not supported "
257                                 "at the moment, because code hasn't been tested."
258                                 <<std::endl;
259
260                 MapSector *sector = n->getValue();
261                 assert(sector->getId() == MAPSECTOR_SERVER);
262                 return (ServerMapSector*)sector;
263         }
264         else
265         {
266                 sector = new ServerMapSector(parent, p2d);
267                 sectors.insert(p2d, sector);
268         }
269
270         /*
271                 Set stuff in sector
272         */
273
274         // Nothing here
275
276         return sector;
277 }
278
279 #ifndef SERVER
280 /*
281         ClientMapSector
282 */
283
284 ClientMapSector::ClientMapSector(NodeContainer *parent, v2s16 pos):
285                 MapSector(parent, pos)
286 {
287 }
288
289 ClientMapSector::~ClientMapSector()
290 {
291 }
292
293 void ClientMapSector::deSerialize(std::istream &is)
294 {
295         /*
296                 [0] u8 serialization version
297                 [1] s16 corners[0]
298                 [3] s16 corners[1]
299                 [5] s16 corners[2]
300                 [7] s16 corners[3]
301                 size = 9
302                 
303                 In which corners are in these positions
304                 v2s16(0,0),
305                 v2s16(1,0),
306                 v2s16(1,1),
307                 v2s16(0,1),
308         */
309         
310         // Read version
311         u8 version = SER_FMT_VER_INVALID;
312         is.read((char*)&version, 1);
313         
314         if(!ser_ver_supported(version))
315                 throw VersionMismatchException("ERROR: MapSector format not supported");
316         
317         u8 buf[2];
318         
319         // Dummy read corners
320         is.read((char*)buf, 2);
321         is.read((char*)buf, 2);
322         is.read((char*)buf, 2);
323         is.read((char*)buf, 2);
324         
325         /*
326                 Set stuff in sector
327         */
328         
329         // Nothing here
330
331 }
332 #endif // !SERVER
333
334 //END