Modernize client code (#6250)
[oweals/minetest.git] / src / mapsector.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 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 Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser 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 "exceptions.h"
22 #include "mapblock.h"
23 #include "serialization.h"
24
25 MapSector::MapSector(Map *parent, v2s16 pos, IGameDef *gamedef):
26                 m_parent(parent),
27                 m_pos(pos),
28                 m_gamedef(gamedef)
29 {
30 }
31
32 MapSector::~MapSector()
33 {
34         deleteBlocks();
35 }
36
37 void MapSector::deleteBlocks()
38 {
39         // Clear cache
40         m_block_cache = nullptr;
41
42         // Delete all
43         for (std::unordered_map<s16, MapBlock*>::iterator i = m_blocks.begin();
44                         i != m_blocks.end(); ++i) {
45                 delete i->second;
46         }
47
48         // Clear container
49         m_blocks.clear();
50 }
51
52 MapBlock * MapSector::getBlockBuffered(s16 y)
53 {
54         MapBlock *block;
55
56         if (m_block_cache && y == m_block_cache_y) {
57                 return m_block_cache;
58         }
59
60         // If block doesn't exist, return NULL
61         std::unordered_map<s16, MapBlock*>::const_iterator n = m_blocks.find(y);
62         block = (n != m_blocks.end() ? n->second : nullptr);
63
64         // Cache the last result
65         m_block_cache_y = y;
66         m_block_cache = block;
67
68         return block;
69 }
70
71 MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
72 {
73         return getBlockBuffered(y);
74 }
75
76 MapBlock * MapSector::createBlankBlockNoInsert(s16 y)
77 {
78         assert(getBlockBuffered(y) == NULL);    // Pre-condition
79
80         v3s16 blockpos_map(m_pos.X, y, m_pos.Y);
81
82         MapBlock *block = new MapBlock(m_parent, blockpos_map, m_gamedef);
83
84         return block;
85 }
86
87 MapBlock * MapSector::createBlankBlock(s16 y)
88 {
89         MapBlock *block = createBlankBlockNoInsert(y);
90
91         m_blocks[y] = block;
92
93         return block;
94 }
95
96 void MapSector::insertBlock(MapBlock *block)
97 {
98         s16 block_y = block->getPos().Y;
99
100         MapBlock *block2 = getBlockBuffered(block_y);
101         if (block2) {
102                 throw AlreadyExistsException("Block already exists");
103         }
104
105         v2s16 p2d(block->getPos().X, block->getPos().Z);
106         assert(p2d == m_pos);
107
108         // Insert into container
109         m_blocks[block_y] = block;
110 }
111
112 void MapSector::deleteBlock(MapBlock *block)
113 {
114         s16 block_y = block->getPos().Y;
115
116         // Clear from cache
117         m_block_cache = nullptr;
118
119         // Remove from container
120         m_blocks.erase(block_y);
121
122         // Delete
123         delete block;
124 }
125
126 void MapSector::getBlocks(MapBlockVect &dest)
127 {
128         for (std::unordered_map<s16, MapBlock*>::iterator bi = m_blocks.begin();
129                 bi != m_blocks.end(); ++bi) {
130                 dest.push_back(bi->second);
131         }
132 }
133
134 /*
135         ServerMapSector
136 */
137
138 ServerMapSector::ServerMapSector(Map *parent, v2s16 pos, IGameDef *gamedef):
139                 MapSector(parent, pos, gamedef)
140 {
141 }
142
143 ServerMapSector::~ServerMapSector()
144 {
145 }
146
147 void ServerMapSector::serialize(std::ostream &os, u8 version)
148 {
149         if(!ser_ver_supported(version))
150                 throw VersionMismatchException("ERROR: MapSector format not supported");
151
152         /*
153                 [0] u8 serialization version
154                 + heightmap data
155         */
156
157         // Server has both of these, no need to support not having them.
158         //assert(m_objects != NULL);
159
160         // Write version
161         os.write((char*)&version, 1);
162
163         /*
164                 Add stuff here, if needed
165         */
166
167 }
168
169 ServerMapSector* ServerMapSector::deSerialize(
170                 std::istream &is,
171                 Map *parent,
172                 v2s16 p2d,
173                 std::map<v2s16, MapSector*> & sectors,
174                 IGameDef *gamedef
175         )
176 {
177         /*
178                 [0] u8 serialization version
179                 + heightmap data
180         */
181
182         /*
183                 Read stuff
184         */
185
186         // Read version
187         u8 version = SER_FMT_VER_INVALID;
188         is.read((char*)&version, 1);
189
190         if(!ser_ver_supported(version))
191                 throw VersionMismatchException("ERROR: MapSector format not supported");
192
193         /*
194                 Add necessary reading stuff here
195         */
196
197         /*
198                 Get or create sector
199         */
200
201         ServerMapSector *sector = NULL;
202
203         std::map<v2s16, MapSector*>::iterator n = sectors.find(p2d);
204
205         if(n != sectors.end())
206         {
207                 warningstream<<"deSerializing existent sectors not supported "
208                                 "at the moment, because code hasn't been tested."
209                                 <<std::endl;
210
211                 MapSector *sector = n->second;
212                 assert(sector->getId() == MAPSECTOR_SERVER);
213                 return (ServerMapSector*)sector;
214         }
215         else
216         {
217                 sector = new ServerMapSector(parent, p2d, gamedef);
218                 sectors[p2d] = sector;
219         }
220
221         /*
222                 Set stuff in sector
223         */
224
225         // Nothing here
226
227         return sector;
228 }
229
230 #ifndef SERVER
231 /*
232         ClientMapSector
233 */
234
235 ClientMapSector::ClientMapSector(Map *parent, v2s16 pos, IGameDef *gamedef):
236                 MapSector(parent, pos, gamedef)
237 {
238 }
239
240 ClientMapSector::~ClientMapSector()
241 {
242 }
243
244 #endif // !SERVER
245
246 //END