Line data Source code
1 : /*
2 : Minetest
3 : Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
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 "objdef.h"
21 : #include "util/numeric.h"
22 : #include "log.h"
23 : #include "gamedef.h"
24 :
25 0 : ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type)
26 : {
27 0 : m_objtype = type;
28 0 : m_ndef = gamedef ? gamedef->getNodeDefManager() : NULL;
29 0 : }
30 :
31 :
32 0 : ObjDefManager::~ObjDefManager()
33 : {
34 0 : for (size_t i = 0; i != m_objects.size(); i++)
35 0 : delete m_objects[i];
36 0 : }
37 :
38 :
39 0 : ObjDefHandle ObjDefManager::add(ObjDef *obj)
40 : {
41 : assert(obj);
42 :
43 0 : if (obj->name.length() && getByName(obj->name))
44 0 : return OBJDEF_INVALID_HANDLE;
45 :
46 0 : u32 index = addRaw(obj);
47 0 : if (index == OBJDEF_INVALID_INDEX)
48 0 : return OBJDEF_INVALID_HANDLE;
49 :
50 0 : obj->handle = createHandle(index, m_objtype, obj->uid);
51 0 : return obj->handle;
52 : }
53 :
54 :
55 0 : ObjDef *ObjDefManager::get(ObjDefHandle handle) const
56 : {
57 0 : u32 index = validateHandle(handle);
58 0 : return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL;
59 : }
60 :
61 :
62 0 : ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj)
63 : {
64 0 : u32 index = validateHandle(handle);
65 0 : if (index == OBJDEF_INVALID_INDEX)
66 0 : return NULL;
67 :
68 0 : ObjDef *oldobj = setRaw(index, obj);
69 :
70 0 : obj->uid = oldobj->uid;
71 0 : obj->index = oldobj->index;
72 0 : obj->handle = oldobj->handle;
73 :
74 0 : return oldobj;
75 : }
76 :
77 :
78 0 : u32 ObjDefManager::addRaw(ObjDef *obj)
79 : {
80 0 : size_t nobjects = m_objects.size();
81 0 : if (nobjects >= OBJDEF_MAX_ITEMS)
82 0 : return -1;
83 :
84 0 : obj->index = nobjects;
85 :
86 : // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE
87 : // is not possible. The slight randomness bias isn't very significant.
88 0 : obj->uid = myrand() & OBJDEF_UID_MASK;
89 0 : if (obj->uid == 0)
90 0 : obj->uid = 1;
91 :
92 0 : m_objects.push_back(obj);
93 :
94 0 : infostream << "ObjDefManager: added " << getObjectTitle()
95 0 : << ": name=\"" << obj->name
96 0 : << "\" index=" << obj->index
97 0 : << " uid=" << obj->uid
98 0 : << std::endl;
99 :
100 0 : return nobjects;
101 : }
102 :
103 :
104 0 : ObjDef *ObjDefManager::getRaw(u32 index) const
105 : {
106 0 : return m_objects[index];
107 : }
108 :
109 :
110 0 : ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj)
111 : {
112 0 : ObjDef *old_obj = m_objects[index];
113 0 : m_objects[index] = obj;
114 0 : return old_obj;
115 : }
116 :
117 :
118 0 : ObjDef *ObjDefManager::getByName(const std::string &name) const
119 : {
120 0 : for (size_t i = 0; i != m_objects.size(); i++) {
121 0 : ObjDef *obj = m_objects[i];
122 0 : if (obj && !strcasecmp(name.c_str(), obj->name.c_str()))
123 0 : return obj;
124 : }
125 :
126 0 : return NULL;
127 : }
128 :
129 :
130 0 : void ObjDefManager::clear()
131 : {
132 0 : for (size_t i = 0; i != m_objects.size(); i++)
133 0 : delete m_objects[i];
134 :
135 0 : m_objects.clear();
136 0 : }
137 :
138 :
139 0 : u32 ObjDefManager::validateHandle(ObjDefHandle handle) const
140 : {
141 : ObjDefType type;
142 : u32 index;
143 : u32 uid;
144 :
145 : bool is_valid =
146 0 : (handle != OBJDEF_INVALID_HANDLE) &&
147 0 : decodeHandle(handle, &index, &type, &uid) &&
148 0 : (type == m_objtype) &&
149 0 : (index < m_objects.size()) &&
150 0 : (m_objects[index]->uid == uid);
151 :
152 0 : return is_valid ? index : -1;
153 : }
154 :
155 :
156 0 : ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid)
157 : {
158 0 : ObjDefHandle handle = 0;
159 0 : set_bits(&handle, 0, 18, index);
160 0 : set_bits(&handle, 18, 6, type);
161 0 : set_bits(&handle, 24, 7, uid);
162 :
163 0 : u32 parity = calc_parity(handle);
164 0 : set_bits(&handle, 31, 1, parity);
165 :
166 0 : return handle ^ OBJDEF_HANDLE_SALT;
167 : }
168 :
169 :
170 0 : bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index,
171 : ObjDefType *type, u32 *uid)
172 : {
173 0 : handle ^= OBJDEF_HANDLE_SALT;
174 :
175 0 : u32 parity = get_bits(handle, 31, 1);
176 0 : set_bits(&handle, 31, 1, 0);
177 0 : if (parity != calc_parity(handle))
178 0 : return false;
179 :
180 0 : *index = get_bits(handle, 0, 18);
181 0 : *type = (ObjDefType)get_bits(handle, 18, 6);
182 0 : *uid = get_bits(handle, 24, 7);
183 0 : return true;
184 3 : }
|