diff options
author | kwolekr <kwolekr@minetest.net> | 2015-05-18 22:30:25 -0400 |
---|---|---|
committer | kwolekr <kwolekr@minetest.net> | 2015-05-18 22:30:25 -0400 |
commit | 6c5a6967ecc162befc44f1adf15bcc9d11658ff7 (patch) | |
tree | d6a14c632b4f7be47b5d5359067510e129221a5a /src/objdef.cpp | |
parent | 497299afd62e2f9b18dbf2a366bb22996e73102b (diff) | |
download | minetest-6c5a6967ecc162befc44f1adf15bcc9d11658ff7.tar.gz minetest-6c5a6967ecc162befc44f1adf15bcc9d11658ff7.tar.bz2 minetest-6c5a6967ecc162befc44f1adf15bcc9d11658ff7.zip |
Split ObjDef/ObjDefManager out to objdef.cpp
Diffstat (limited to 'src/objdef.cpp')
-rw-r--r-- | src/objdef.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/objdef.cpp b/src/objdef.cpp new file mode 100644 index 000000000..bdf9c4dfc --- /dev/null +++ b/src/objdef.cpp @@ -0,0 +1,185 @@ +/* +Minetest +Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "objdef.h" +#include "util/numeric.h" +#include "debug.h" +#include "log.h" +#include "gamedef.h" + +ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type) +{ + m_objtype = type; + m_ndef = gamedef ? gamedef->getNodeDefManager() : NULL; +} + + +ObjDefManager::~ObjDefManager() +{ + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; +} + + +ObjDefHandle ObjDefManager::add(ObjDef *obj) +{ + assert(obj); + + if (obj->name.length() && getByName(obj->name)) + return OBJDEF_INVALID_HANDLE; + + u32 index = addRaw(obj); + if (index == OBJDEF_INVALID_INDEX) + return OBJDEF_INVALID_HANDLE; + + obj->handle = createHandle(index, m_objtype, obj->uid); + return obj->handle; +} + + +ObjDef *ObjDefManager::get(ObjDefHandle handle) const +{ + u32 index = validateHandle(handle); + return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL; +} + + +ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj) +{ + u32 index = validateHandle(handle); + if (index == OBJDEF_INVALID_INDEX) + return NULL; + + ObjDef *oldobj = setRaw(index, obj); + + obj->uid = oldobj->uid; + obj->index = oldobj->index; + obj->handle = oldobj->handle; + + return oldobj; +} + + +u32 ObjDefManager::addRaw(ObjDef *obj) +{ + size_t nobjects = m_objects.size(); + if (nobjects >= OBJDEF_MAX_ITEMS) + return -1; + + obj->index = nobjects; + + // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE + // is not possible. The slight randomness bias isn't very significant. + obj->uid = myrand() & OBJDEF_UID_MASK; + if (obj->uid == 0) + obj->uid = 1; + + m_objects.push_back(obj); + + infostream << "ObjDefManager: added " << getObjectTitle() + << ": name=\"" << obj->name + << "\" index=" << obj->index + << " uid=" << obj->uid + << std::endl; + + return nobjects; +} + + +ObjDef *ObjDefManager::getRaw(u32 index) const +{ + return m_objects[index]; +} + + +ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj) +{ + ObjDef *old_obj = m_objects[index]; + m_objects[index] = obj; + return old_obj; +} + + +ObjDef *ObjDefManager::getByName(const std::string &name) const +{ + for (size_t i = 0; i != m_objects.size(); i++) { + ObjDef *obj = m_objects[i]; + if (obj && !strcasecmp(name.c_str(), obj->name.c_str())) + return obj; + } + + return NULL; +} + + +void ObjDefManager::clear() +{ + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; + + m_objects.clear(); +} + + +u32 ObjDefManager::validateHandle(ObjDefHandle handle) const +{ + ObjDefType type; + u32 index; + u32 uid; + + bool is_valid = + (handle != OBJDEF_INVALID_HANDLE) && + decodeHandle(handle, &index, &type, &uid) && + (type == m_objtype) && + (index < m_objects.size()) && + (m_objects[index]->uid == uid); + + return is_valid ? index : -1; +} + + +ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid) +{ + ObjDefHandle handle = 0; + set_bits(&handle, 0, 18, index); + set_bits(&handle, 18, 6, type); + set_bits(&handle, 24, 7, uid); + + u32 parity = calc_parity(handle); + set_bits(&handle, 31, 1, parity); + + return handle ^ OBJDEF_HANDLE_SALT; +} + + +bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index, + ObjDefType *type, u32 *uid) +{ + handle ^= OBJDEF_HANDLE_SALT; + + u32 parity = get_bits(handle, 31, 1); + set_bits(&handle, 31, 1, 0); + if (parity != calc_parity(handle)) + return false; + + *index = get_bits(handle, 0, 18); + *type = (ObjDefType)get_bits(handle, 18, 6); + *uid = get_bits(handle, 24, 7); + return true; +} |