nodemetadata.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  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 "nodemetadata.h"
  17. #include "exceptions.h"
  18. #include "gamedef.h"
  19. #include "inventory.h"
  20. #include "irrlicht_changes/printing.h"
  21. #include "log.h"
  22. #include "debug.h"
  23. #include "util/serialize.h"
  24. #include "constants.h" // MAP_BLOCKSIZE
  25. #include <sstream>
  26. /*
  27. NodeMetadata
  28. */
  29. NodeMetadata::NodeMetadata(IItemDefManager *item_def_mgr):
  30. m_inventory(new Inventory(item_def_mgr))
  31. {}
  32. NodeMetadata::~NodeMetadata()
  33. {
  34. delete m_inventory;
  35. }
  36. void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
  37. {
  38. int num_vars = disk ? m_stringvars.size() : countNonPrivate();
  39. writeU32(os, num_vars);
  40. for (const auto &sv : m_stringvars) {
  41. bool priv = isPrivate(sv.first);
  42. if (!disk && priv)
  43. continue;
  44. os << serializeString16(sv.first);
  45. os << serializeString32(sv.second);
  46. if (version >= 2)
  47. writeU8(os, (priv) ? 1 : 0);
  48. }
  49. m_inventory->serialize(os);
  50. }
  51. void NodeMetadata::deSerialize(std::istream &is, u8 version)
  52. {
  53. clear();
  54. int num_vars = readU32(is);
  55. for(int i=0; i<num_vars; i++){
  56. std::string name = deSerializeString16(is);
  57. std::string var = deSerializeString32(is);
  58. m_stringvars[name] = var;
  59. if (version >= 2) {
  60. if (readU8(is) == 1)
  61. markPrivate(name, true);
  62. }
  63. }
  64. m_inventory->deSerialize(is);
  65. }
  66. void NodeMetadata::clear()
  67. {
  68. SimpleMetadata::clear();
  69. m_privatevars.clear();
  70. m_inventory->clear();
  71. }
  72. bool NodeMetadata::empty() const
  73. {
  74. return SimpleMetadata::empty() && m_inventory->getLists().empty();
  75. }
  76. void NodeMetadata::markPrivate(const std::string &name, bool set)
  77. {
  78. if (set)
  79. m_privatevars.insert(name);
  80. else
  81. m_privatevars.erase(name);
  82. }
  83. int NodeMetadata::countNonPrivate() const
  84. {
  85. // m_privatevars can contain names not actually present
  86. // DON'T: return m_stringvars.size() - m_privatevars.size();
  87. int n = 0;
  88. for (const auto &sv : m_stringvars) {
  89. if (!isPrivate(sv.first))
  90. n++;
  91. }
  92. return n;
  93. }
  94. /*
  95. NodeMetadataList
  96. */
  97. void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
  98. bool absolute_pos, bool include_empty) const
  99. {
  100. /*
  101. Version 0 is a placeholder for "nothing to see here; go away."
  102. */
  103. u16 count = include_empty ? m_data.size() : countNonEmpty();
  104. if (count == 0) {
  105. writeU8(os, 0); // version
  106. return;
  107. }
  108. u8 version = (blockver > 27) ? 2 : 1;
  109. writeU8(os, version);
  110. writeU16(os, count);
  111. for (NodeMetadataMap::const_iterator
  112. i = m_data.begin();
  113. i != m_data.end(); ++i) {
  114. v3s16 p = i->first;
  115. NodeMetadata *data = i->second;
  116. if (!include_empty && data->empty())
  117. continue;
  118. if (absolute_pos) {
  119. writeS16(os, p.X);
  120. writeS16(os, p.Y);
  121. writeS16(os, p.Z);
  122. } else {
  123. // Serialize positions within a mapblock
  124. u16 p16 = (p.Z * MAP_BLOCKSIZE + p.Y) * MAP_BLOCKSIZE + p.X;
  125. writeU16(os, p16);
  126. }
  127. data->serialize(os, version, disk);
  128. }
  129. }
  130. void NodeMetadataList::deSerialize(std::istream &is,
  131. IItemDefManager *item_def_mgr, bool absolute_pos)
  132. {
  133. clear();
  134. u8 version = readU8(is);
  135. if (version == 0) {
  136. // Nothing
  137. return;
  138. }
  139. if (version > 2) {
  140. std::string err_str = std::string(FUNCTION_NAME)
  141. + ": version " + itos(version) + " not supported";
  142. infostream << err_str << std::endl;
  143. throw SerializationError(err_str);
  144. }
  145. u16 count = readU16(is);
  146. for (u16 i = 0; i < count; i++) {
  147. v3s16 p;
  148. if (absolute_pos) {
  149. p.X = readS16(is);
  150. p.Y = readS16(is);
  151. p.Z = readS16(is);
  152. } else {
  153. u16 p16 = readU16(is);
  154. p.X = p16 & (MAP_BLOCKSIZE - 1);
  155. p16 /= MAP_BLOCKSIZE;
  156. p.Y = p16 & (MAP_BLOCKSIZE - 1);
  157. p16 /= MAP_BLOCKSIZE;
  158. p.Z = p16;
  159. }
  160. if (m_data.find(p) != m_data.end()) {
  161. warningstream << "NodeMetadataList::deSerialize(): "
  162. << "already set data at position " << p
  163. << ": Ignoring." << std::endl;
  164. continue;
  165. }
  166. NodeMetadata *data = new NodeMetadata(item_def_mgr);
  167. data->deSerialize(is, version);
  168. m_data[p] = data;
  169. }
  170. }
  171. NodeMetadataList::~NodeMetadataList()
  172. {
  173. clear();
  174. }
  175. std::vector<v3s16> NodeMetadataList::getAllKeys()
  176. {
  177. std::vector<v3s16> keys;
  178. keys.reserve(m_data.size());
  179. for (const auto &it : m_data)
  180. keys.push_back(it.first);
  181. return keys;
  182. }
  183. NodeMetadata *NodeMetadataList::get(v3s16 p)
  184. {
  185. NodeMetadataMap::const_iterator n = m_data.find(p);
  186. if (n == m_data.end())
  187. return nullptr;
  188. return n->second;
  189. }
  190. void NodeMetadataList::remove(v3s16 p)
  191. {
  192. NodeMetadata *olddata = get(p);
  193. if (olddata) {
  194. if (m_is_metadata_owner) {
  195. // clearing can throw an exception due to the invlist resize lock,
  196. // which we don't want to happen in the noexcept destructor
  197. // => call clear before
  198. olddata->clear();
  199. delete olddata;
  200. }
  201. m_data.erase(p);
  202. }
  203. }
  204. void NodeMetadataList::set(v3s16 p, NodeMetadata *d)
  205. {
  206. remove(p);
  207. m_data.emplace(p, d);
  208. }
  209. void NodeMetadataList::clear()
  210. {
  211. if (m_is_metadata_owner) {
  212. NodeMetadataMap::const_iterator it;
  213. for (it = m_data.begin(); it != m_data.end(); ++it)
  214. delete it->second;
  215. }
  216. m_data.clear();
  217. }
  218. int NodeMetadataList::countNonEmpty() const
  219. {
  220. int n = 0;
  221. for (const auto &it : m_data) {
  222. if (!it.second->empty())
  223. n++;
  224. }
  225. return n;
  226. }