objdef.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "objdef.h"
  17. #include "util/numeric.h"
  18. #include "log.h"
  19. #include "gamedef.h"
  20. ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type)
  21. {
  22. m_objtype = type;
  23. m_ndef = gamedef ? gamedef->getNodeDefManager() : NULL;
  24. }
  25. ObjDefManager::~ObjDefManager()
  26. {
  27. for (size_t i = 0; i != m_objects.size(); i++)
  28. delete m_objects[i];
  29. }
  30. ObjDefHandle ObjDefManager::add(ObjDef *obj)
  31. {
  32. assert(obj);
  33. if (obj->name.length() && getByName(obj->name))
  34. return OBJDEF_INVALID_HANDLE;
  35. u32 index = addRaw(obj);
  36. if (index == OBJDEF_INVALID_INDEX)
  37. return OBJDEF_INVALID_HANDLE;
  38. obj->handle = createHandle(index, m_objtype, obj->uid);
  39. return obj->handle;
  40. }
  41. ObjDef *ObjDefManager::get(ObjDefHandle handle) const
  42. {
  43. u32 index = validateHandle(handle);
  44. return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL;
  45. }
  46. ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj)
  47. {
  48. u32 index = validateHandle(handle);
  49. if (index == OBJDEF_INVALID_INDEX)
  50. return NULL;
  51. ObjDef *oldobj = setRaw(index, obj);
  52. obj->uid = oldobj->uid;
  53. obj->index = oldobj->index;
  54. obj->handle = oldobj->handle;
  55. return oldobj;
  56. }
  57. u32 ObjDefManager::addRaw(ObjDef *obj)
  58. {
  59. size_t nobjects = m_objects.size();
  60. if (nobjects >= OBJDEF_MAX_ITEMS)
  61. return -1;
  62. obj->index = nobjects;
  63. // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE
  64. // is not possible. The slight randomness bias isn't very significant.
  65. obj->uid = myrand() & OBJDEF_UID_MASK;
  66. if (obj->uid == 0)
  67. obj->uid = 1;
  68. m_objects.push_back(obj);
  69. infostream << "ObjDefManager: added " << getObjectTitle()
  70. << ": name=\"" << obj->name
  71. << "\" index=" << obj->index
  72. << " uid=" << obj->uid
  73. << std::endl;
  74. return nobjects;
  75. }
  76. ObjDef *ObjDefManager::getRaw(u32 index) const
  77. {
  78. return m_objects[index];
  79. }
  80. ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj)
  81. {
  82. ObjDef *old_obj = m_objects[index];
  83. m_objects[index] = obj;
  84. return old_obj;
  85. }
  86. ObjDef *ObjDefManager::getByName(const std::string &name) const
  87. {
  88. for (size_t i = 0; i != m_objects.size(); i++) {
  89. ObjDef *obj = m_objects[i];
  90. if (obj && !strcasecmp(name.c_str(), obj->name.c_str()))
  91. return obj;
  92. }
  93. return NULL;
  94. }
  95. void ObjDefManager::clear()
  96. {
  97. for (size_t i = 0; i != m_objects.size(); i++)
  98. delete m_objects[i];
  99. m_objects.clear();
  100. }
  101. u32 ObjDefManager::validateHandle(ObjDefHandle handle) const
  102. {
  103. ObjDefType type;
  104. u32 index;
  105. u32 uid;
  106. bool is_valid =
  107. (handle != OBJDEF_INVALID_HANDLE) &&
  108. decodeHandle(handle, &index, &type, &uid) &&
  109. (type == m_objtype) &&
  110. (index < m_objects.size()) &&
  111. (m_objects[index]->uid == uid);
  112. return is_valid ? index : -1;
  113. }
  114. ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid)
  115. {
  116. ObjDefHandle handle = 0;
  117. set_bits(&handle, 0, 18, index);
  118. set_bits(&handle, 18, 6, type);
  119. set_bits(&handle, 24, 7, uid);
  120. u32 parity = calc_parity(handle);
  121. set_bits(&handle, 31, 1, parity);
  122. return handle ^ OBJDEF_HANDLE_SALT;
  123. }
  124. bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index,
  125. ObjDefType *type, u32 *uid)
  126. {
  127. handle ^= OBJDEF_HANDLE_SALT;
  128. u32 parity = get_bits(handle, 31, 1);
  129. set_bits(&handle, 31, 1, 0);
  130. if (parity != calc_parity(handle))
  131. return false;
  132. *index = get_bits(handle, 0, 18);
  133. *type = (ObjDefType)get_bits(handle, 18, 6);
  134. *uid = get_bits(handle, 24, 7);
  135. return true;
  136. }
  137. // Cloning
  138. void ObjDef::cloneTo(ObjDef *def) const
  139. {
  140. def->index = index;
  141. def->uid = uid;
  142. def->handle = handle;
  143. def->name = name;
  144. }
  145. void ObjDefManager::cloneTo(ObjDefManager *mgr) const
  146. {
  147. mgr->m_ndef = m_ndef;
  148. mgr->m_objects.reserve(m_objects.size());
  149. for (const auto &obj : m_objects)
  150. mgr->m_objects.push_back(obj->clone());
  151. mgr->m_objtype = m_objtype;
  152. }