Switch the license to be LGPLv2/later, with small parts still remaining as GPLv2...
[oweals/minetest.git] / src / nodemetadata.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 "nodemetadata.h"
21 #include "utility.h"
22 #include "exceptions.h"
23 #include "gamedef.h"
24 #include "inventory.h"
25 #include <sstream>
26 #include "log.h"
27
28 /*
29         NodeMetadata
30 */
31
32 NodeMetadata::NodeMetadata(IGameDef *gamedef):
33         m_stringvars(),
34         m_inventory(new Inventory(gamedef->idef()))
35 {
36 }
37
38 NodeMetadata::~NodeMetadata()
39 {
40         delete m_inventory;
41 }
42
43 void NodeMetadata::serialize(std::ostream &os) const
44 {
45         int num_vars = m_stringvars.size();
46         writeU32(os, num_vars);
47         for(std::map<std::string, std::string>::const_iterator
48                         i = m_stringvars.begin(); i != m_stringvars.end(); i++){
49                 os<<serializeString(i->first);
50                 os<<serializeLongString(i->second);
51         }
52
53         m_inventory->serialize(os);
54 }
55
56 void NodeMetadata::deSerialize(std::istream &is)
57 {
58         m_stringvars.clear();
59         int num_vars = readU32(is);
60         for(int i=0; i<num_vars; i++){
61                 std::string name = deSerializeString(is);
62                 std::string var = deSerializeLongString(is);
63                 m_stringvars[name] = var;
64         }
65
66         m_inventory->deSerialize(is);
67 }
68
69 void NodeMetadata::clear()
70 {
71         m_stringvars.clear();
72         m_inventory->clear();
73 }
74
75 /*
76         NodeMetadataList
77 */
78
79 void NodeMetadataList::serialize(std::ostream &os) const
80 {
81         /*
82                 Version 0 is a placeholder for "nothing to see here; go away."
83         */
84
85         if(m_data.size() == 0){
86                 writeU8(os, 0); // version
87                 return;
88         }
89
90         writeU8(os, 1); // version
91
92         u16 count = m_data.size();
93         writeU16(os, count);
94
95         for(std::map<v3s16, NodeMetadata*>::const_iterator
96                         i = m_data.begin();
97                         i != m_data.end(); i++)
98         {
99                 v3s16 p = i->first;
100                 NodeMetadata *data = i->second;
101
102                 u16 p16 = p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X;
103                 writeU16(os, p16);
104
105                 data->serialize(os);
106         }
107 }
108
109 void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef)
110 {
111         m_data.clear();
112
113         u8 version = readU8(is);
114         
115         if(version == 0){
116                 // Nothing
117                 return;
118         }
119
120         if(version != 1){
121                 infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
122                                 <<std::endl;
123                 throw SerializationError("NodeMetadataList::deSerialize");
124         }
125
126         u16 count = readU16(is);
127
128         for(u16 i=0; i<count; i++)
129         {
130                 u16 p16 = readU16(is);
131
132                 v3s16 p(0,0,0);
133                 p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
134                 p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
135                 p.Y += p16 / MAP_BLOCKSIZE;
136                 p16 -= p.Y * MAP_BLOCKSIZE;
137                 p.X += p16;
138
139                 if(m_data.find(p) != m_data.end())
140                 {
141                         infostream<<"WARNING: NodeMetadataList::deSerialize(): "
142                                         <<"already set data at position"
143                                         <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
144                                         <<std::endl;
145                         continue;
146                 }
147
148                 NodeMetadata *data = new NodeMetadata(gamedef);
149                 data->deSerialize(is);
150                 m_data[p] = data;
151         }
152 }
153
154 NodeMetadataList::~NodeMetadataList()
155 {
156         clear();
157 }
158
159 NodeMetadata* NodeMetadataList::get(v3s16 p)
160 {
161         std::map<v3s16, NodeMetadata*>::const_iterator n = m_data.find(p);
162         if(n == m_data.end())
163                 return NULL;
164         return n->second;
165 }
166
167 void NodeMetadataList::remove(v3s16 p)
168 {
169         NodeMetadata *olddata = get(p);
170         if(olddata)
171         {
172                 delete olddata;
173                 m_data.erase(p);
174         }
175 }
176
177 void NodeMetadataList::set(v3s16 p, NodeMetadata *d)
178 {
179         remove(p);
180         m_data.insert(std::make_pair(p, d));
181 }
182
183 void NodeMetadataList::clear()
184 {
185         for(std::map<v3s16, NodeMetadata*>::iterator
186                         i = m_data.begin();
187                         i != m_data.end(); i++)
188         {
189                 delete i->second;
190         }
191         m_data.clear();
192 }