3 Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
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.
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.
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.
21 #include "util/numeric.h"
26 ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type)
29 m_ndef = gamedef ? gamedef->getNodeDefManager() : NULL;
33 ObjDefManager::~ObjDefManager()
35 for (size_t i = 0; i != m_objects.size(); i++)
40 ObjDefHandle ObjDefManager::add(ObjDef *obj)
44 if (obj->name.length() && getByName(obj->name))
45 return OBJDEF_INVALID_HANDLE;
47 u32 index = addRaw(obj);
48 if (index == OBJDEF_INVALID_INDEX)
49 return OBJDEF_INVALID_HANDLE;
51 obj->handle = createHandle(index, m_objtype, obj->uid);
56 ObjDef *ObjDefManager::get(ObjDefHandle handle) const
58 u32 index = validateHandle(handle);
59 return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL;
63 ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj)
65 u32 index = validateHandle(handle);
66 if (index == OBJDEF_INVALID_INDEX)
69 ObjDef *oldobj = setRaw(index, obj);
71 obj->uid = oldobj->uid;
72 obj->index = oldobj->index;
73 obj->handle = oldobj->handle;
79 u32 ObjDefManager::addRaw(ObjDef *obj)
81 size_t nobjects = m_objects.size();
82 if (nobjects >= OBJDEF_MAX_ITEMS)
85 obj->index = nobjects;
87 // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE
88 // is not possible. The slight randomness bias isn't very significant.
89 obj->uid = myrand() & OBJDEF_UID_MASK;
93 m_objects.push_back(obj);
95 infostream << "ObjDefManager: added " << getObjectTitle()
96 << ": name=\"" << obj->name
97 << "\" index=" << obj->index
98 << " uid=" << obj->uid
105 ObjDef *ObjDefManager::getRaw(u32 index) const
107 return m_objects[index];
111 ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj)
113 ObjDef *old_obj = m_objects[index];
114 m_objects[index] = obj;
119 ObjDef *ObjDefManager::getByName(const std::string &name) const
121 for (size_t i = 0; i != m_objects.size(); i++) {
122 ObjDef *obj = m_objects[i];
123 if (obj && !strcasecmp(name.c_str(), obj->name.c_str()))
131 void ObjDefManager::clear()
133 for (size_t i = 0; i != m_objects.size(); i++)
140 u32 ObjDefManager::validateHandle(ObjDefHandle handle) const
147 (handle != OBJDEF_INVALID_HANDLE) &&
148 decodeHandle(handle, &index, &type, &uid) &&
149 (type == m_objtype) &&
150 (index < m_objects.size()) &&
151 (m_objects[index]->uid == uid);
153 return is_valid ? index : -1;
157 ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid)
159 ObjDefHandle handle = 0;
160 set_bits(&handle, 0, 18, index);
161 set_bits(&handle, 18, 6, type);
162 set_bits(&handle, 24, 7, uid);
164 u32 parity = calc_parity(handle);
165 set_bits(&handle, 31, 1, parity);
167 return handle ^ OBJDEF_HANDLE_SALT;
171 bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index,
172 ObjDefType *type, u32 *uid)
174 handle ^= OBJDEF_HANDLE_SALT;
176 u32 parity = get_bits(handle, 31, 1);
177 set_bits(&handle, 31, 1, 0);
178 if (parity != calc_parity(handle))
181 *index = get_bits(handle, 0, 18);
182 *type = (ObjDefType)get_bits(handle, 18, 6);
183 *uid = get_bits(handle, 24, 7);