diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index f78b78b9b..2c574bc41 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -182,6 +182,7 @@ LOCAL_SRC_FILES := \ jni/src/nodemetadata.cpp \ jni/src/nodetimer.cpp \ jni/src/noise.cpp \ + jni/src/objdef.cpp \ jni/src/object_properties.cpp \ jni/src/particles.cpp \ jni/src/pathfinder.cpp \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 89be91413..190f4e9bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -330,6 +330,7 @@ set(common_SRCS nodemetadata.cpp nodetimer.cpp noise.cpp + objdef.cpp object_properties.cpp pathfinder.cpp player.cpp diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 1de7fca81..7965730e4 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -1,6 +1,7 @@ /* Minetest -Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2010-2015 kwolekr, Ryan Kwolek +Copyright (C) 2010-2015 celeron55, Perttu Ahola 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 @@ -427,175 +428,8 @@ void GenerateNotifier::getEvents( m_notify_events.clear(); } - /////////////////////////////////////////////////////////////////////////////// - -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; -} - - -/////////////////////////////////////////////////////////////////////////////// - - void MapgenParams::load(const Settings &settings) { std::string seed_str; diff --git a/src/mapgen.h b/src/mapgen.h index b7fecb7a4..351a09bb2 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -186,72 +186,4 @@ struct MapgenFactory { virtual ~MapgenFactory() {} }; -typedef std::map StringMap; -typedef u32 ObjDefHandle; - -#define OBJDEF_INVALID_INDEX ((u32)(-1)) -#define OBJDEF_INVALID_HANDLE 0 -#define OBJDEF_HANDLE_SALT 0x00585e6fu -#define OBJDEF_MAX_ITEMS (1 << 18) -#define OBJDEF_UID_MASK ((1 << 7) - 1) - -enum ObjDefType { - OBJDEF_GENERIC, - OBJDEF_BIOME, - OBJDEF_ORE, - OBJDEF_DECORATION, - OBJDEF_SCHEMATIC, -}; - -class ObjDef { -public: - virtual ~ObjDef() {} - - u32 index; - u32 uid; - ObjDefHandle handle; - std::string name; -}; - -// WARNING: Ownership of ObjDefs is transferred to the ObjDefManager it is -// added/set to. Note that ObjDefs managed by ObjDefManager are NOT refcounted, -// so the same ObjDef instance must not be referenced multiple -class ObjDefManager { -public: - ObjDefManager(IGameDef *gamedef, ObjDefType type); - virtual ~ObjDefManager(); - - virtual const char *getObjectTitle() const { return "ObjDef"; } - - virtual void clear(); - virtual ObjDef *getByName(const std::string &name) const; - - //// Add new/get/set object definitions by handle - virtual ObjDefHandle add(ObjDef *obj); - virtual ObjDef *get(ObjDefHandle handle) const; - virtual ObjDef *set(ObjDefHandle handle, ObjDef *obj); - - //// Raw variants that work on indexes - virtual u32 addRaw(ObjDef *obj); - - // It is generally assumed that getRaw() will always return a valid object - // This won't be true if people do odd things such as call setRaw() with NULL - virtual ObjDef *getRaw(u32 index) const; - virtual ObjDef *setRaw(u32 index, ObjDef *obj); - - size_t getNumObjects() const { return m_objects.size(); } - ObjDefType getType() const { return m_objtype; } - INodeDefManager *getNodeDef() const { return m_ndef; } - - u32 validateHandle(ObjDefHandle handle) const; - static ObjDefHandle createHandle(u32 index, ObjDefType type, u32 uid); - static bool decodeHandle(ObjDefHandle handle, u32 *index, - ObjDefType *type, u32 *uid); - -protected: - INodeDefManager *m_ndef; - std::vector m_objects; - ObjDefType m_objtype; -}; - #endif diff --git a/src/mg_biome.h b/src/mg_biome.h index e289fb16d..8d519f808 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -20,9 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MG_BIOME_HEADER #define MG_BIOME_HEADER -#include "mapgen.h" - -struct NoiseParams; +#include "objdef.h" +#include "nodedef.h" enum BiomeType { diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 8ece5d684..056748918 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -21,9 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_DECORATION_HEADER #include -#include "mapgen.h" +#include "objdef.h" +#include "noise.h" +#include "nodedef.h" -struct NoiseParams; class Mapgen; class MMVManip; class PseudoRandom; diff --git a/src/mg_ore.h b/src/mg_ore.h index cff1622fb..ffe8cfe50 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -20,10 +20,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MG_ORE_HEADER #define MG_ORE_HEADER -#include "util/string.h" -#include "mapgen.h" +#include "objdef.h" +#include "noise.h" +#include "nodedef.h" -struct NoiseParams; class Noise; class Mapgen; class MMVManip; 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 + +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; +} diff --git a/src/objdef.h b/src/objdef.h new file mode 100644 index 000000000..9e0c0b001 --- /dev/null +++ b/src/objdef.h @@ -0,0 +1,97 @@ +/* +Minetest +Copyright (C) 2010-2015 kwolekr, Ryan Kwolek + +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. +*/ + +#ifndef OBJDEF_HEADER +#define OBJDEF_HEADER + +#include +#include +#include "irrlichttypes.h" + +class IGameDef; +class INodeDefManager; + +#define OBJDEF_INVALID_INDEX ((u32)(-1)) +#define OBJDEF_INVALID_HANDLE 0 +#define OBJDEF_HANDLE_SALT 0x00585e6fu +#define OBJDEF_MAX_ITEMS (1 << 18) +#define OBJDEF_UID_MASK ((1 << 7) - 1) + +typedef u32 ObjDefHandle; + +enum ObjDefType { + OBJDEF_GENERIC, + OBJDEF_BIOME, + OBJDEF_ORE, + OBJDEF_DECORATION, + OBJDEF_SCHEMATIC, +}; + +class ObjDef { +public: + virtual ~ObjDef() {} + + u32 index; + u32 uid; + ObjDefHandle handle; + std::string name; +}; + +// WARNING: Ownership of ObjDefs is transferred to the ObjDefManager it is +// added/set to. Note that ObjDefs managed by ObjDefManager are NOT refcounted, +// so the same ObjDef instance must not be referenced multiple +class ObjDefManager { +public: + ObjDefManager(IGameDef *gamedef, ObjDefType type); + virtual ~ObjDefManager(); + + virtual const char *getObjectTitle() const { return "ObjDef"; } + + virtual void clear(); + virtual ObjDef *getByName(const std::string &name) const; + + //// Add new/get/set object definitions by handle + virtual ObjDefHandle add(ObjDef *obj); + virtual ObjDef *get(ObjDefHandle handle) const; + virtual ObjDef *set(ObjDefHandle handle, ObjDef *obj); + + //// Raw variants that work on indexes + virtual u32 addRaw(ObjDef *obj); + + // It is generally assumed that getRaw() will always return a valid object + // This won't be true if people do odd things such as call setRaw() with NULL + virtual ObjDef *getRaw(u32 index) const; + virtual ObjDef *setRaw(u32 index, ObjDef *obj); + + size_t getNumObjects() const { return m_objects.size(); } + ObjDefType getType() const { return m_objtype; } + INodeDefManager *getNodeDef() const { return m_ndef; } + + u32 validateHandle(ObjDefHandle handle) const; + static ObjDefHandle createHandle(u32 index, ObjDefType type, u32 uid); + static bool decodeHandle(ObjDefHandle handle, u32 *index, + ObjDefType *type, u32 *uid); + +protected: + INodeDefManager *m_ndef; + std::vector m_objects; + ObjDefType m_objtype; +}; + +#endif diff --git a/src/unittest/test_objdef.cpp b/src/unittest/test_objdef.cpp index ddb3bc60d..df2633b38 100644 --- a/src/unittest/test_objdef.cpp +++ b/src/unittest/test_objdef.cpp @@ -20,8 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "test.h" #include "exceptions.h" -#include "mapgen.h" - +#include "objdef.h" class TestObjDef : public TestBase { public: diff --git a/src/util/string.h b/src/util/string.h index 4ab5cf3f7..b80e3c9a8 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -25,18 +25,20 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include #include #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) +typedef std::map StringMap; + struct FlagDesc { const char *name; u32 flag; }; - // You must free the returned string! // The returned string is allocated using new wchar_t *narrow_to_wide_c(const char *str);