object_properties.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // Luanti
  2. // SPDX-License-Identifier: LGPL-2.1-or-later
  3. // Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. #include "object_properties.h"
  5. #include "irrlicht_changes/printing.h"
  6. #include "irrlichttypes_bloated.h"
  7. #include "exceptions.h"
  8. #include "log.h"
  9. #include "util/serialize.h"
  10. #include <sstream>
  11. #include <tuple>
  12. static const video::SColor NULL_BGCOLOR{0, 1, 1, 1};
  13. ObjectProperties::ObjectProperties()
  14. {
  15. textures.emplace_back("no_texture.png");
  16. colors.emplace_back(255,255,255,255);
  17. }
  18. std::string ObjectProperties::dump() const
  19. {
  20. std::ostringstream os(std::ios::binary);
  21. os << "hp_max=" << hp_max;
  22. os << ", breath_max=" << breath_max;
  23. os << ", physical=" << physical;
  24. os << ", collideWithObjects=" << collideWithObjects;
  25. os << ", collisionbox=" << collisionbox.MinEdge << "," << collisionbox.MaxEdge;
  26. os << ", visual=" << visual;
  27. os << ", mesh=" << mesh;
  28. os << ", visual_size=" << visual_size;
  29. os << ", textures=[";
  30. for (const std::string &texture : textures) {
  31. os << "\"" << texture << "\" ";
  32. }
  33. os << "]";
  34. os << ", colors=[";
  35. for (const video::SColor &color : colors) {
  36. os << "\"" << color.getAlpha() << "," << color.getRed() << ","
  37. << color.getGreen() << "," << color.getBlue() << "\" ";
  38. }
  39. os << "]";
  40. os << ", spritediv=" << spritediv;
  41. os << ", initial_sprite_basepos=" << initial_sprite_basepos;
  42. os << ", is_visible=" << is_visible;
  43. os << ", makes_footstep_sound=" << makes_footstep_sound;
  44. os << ", automatic_rotate="<< automatic_rotate;
  45. os << ", backface_culling="<< backface_culling;
  46. os << ", glow=" << glow;
  47. os << ", nametag=" << nametag;
  48. os << ", nametag_color=" << "\"" << nametag_color.getAlpha() << "," << nametag_color.getRed()
  49. << "," << nametag_color.getGreen() << "," << nametag_color.getBlue() << "\" ";
  50. if (nametag_bgcolor)
  51. os << ", nametag_bgcolor=" << "\"" << nametag_color.getAlpha() << "," << nametag_color.getRed()
  52. << "," << nametag_color.getGreen() << "," << nametag_color.getBlue() << "\" ";
  53. else
  54. os << ", nametag_bgcolor=null ";
  55. os << ", selectionbox=" << selectionbox.MinEdge << "," << selectionbox.MaxEdge;
  56. os << ", rotate_selectionbox=" << rotate_selectionbox;
  57. os << ", pointable=" << Pointabilities::toStringPointabilityType(pointable);
  58. os << ", static_save=" << static_save;
  59. os << ", eye_height=" << eye_height;
  60. os << ", zoom_fov=" << zoom_fov;
  61. os << ", use_texture_alpha=" << use_texture_alpha;
  62. os << ", damage_texture_modifier=" << damage_texture_modifier;
  63. os << ", shaded=" << shaded;
  64. os << ", show_on_minimap=" << show_on_minimap;
  65. return os.str();
  66. }
  67. static auto tie(const ObjectProperties &o)
  68. {
  69. // Make sure to add new members to this list!
  70. return std::tie(
  71. o.textures, o.colors, o.collisionbox, o.selectionbox, o.visual, o.mesh,
  72. o.damage_texture_modifier, o.nametag, o.infotext, o.wield_item, o.visual_size,
  73. o.nametag_color, o.nametag_bgcolor, o.spritediv, o.initial_sprite_basepos,
  74. o.stepheight, o.automatic_rotate, o.automatic_face_movement_dir_offset,
  75. o.automatic_face_movement_max_rotation_per_sec, o.eye_height, o.zoom_fov,
  76. o.hp_max, o.breath_max, o.glow, o.pointable, o.physical, o.collideWithObjects,
  77. o.rotate_selectionbox, o.is_visible, o.makes_footstep_sound,
  78. o.automatic_face_movement_dir, o.backface_culling, o.static_save, o.use_texture_alpha,
  79. o.shaded, o.show_on_minimap
  80. );
  81. }
  82. bool ObjectProperties::operator==(const ObjectProperties &other) const
  83. {
  84. return tie(*this) == tie(other);
  85. }
  86. bool ObjectProperties::validate()
  87. {
  88. const char *func = "ObjectProperties::validate(): ";
  89. bool ret = true;
  90. // cf. where serializeString16 is used below
  91. for (u32 i = 0; i < textures.size(); i++) {
  92. if (textures[i].size() > U16_MAX) {
  93. warningstream << func << "texture " << (i+1) << " has excessive length, "
  94. "clearing it." << std::endl;
  95. textures[i].clear();
  96. ret = false;
  97. }
  98. }
  99. if (nametag.length() > U16_MAX) {
  100. warningstream << func << "nametag has excessive length, clearing it." << std::endl;
  101. nametag.clear();
  102. ret = false;
  103. }
  104. if (infotext.length() > U16_MAX) {
  105. warningstream << func << "infotext has excessive length, clearing it." << std::endl;
  106. infotext.clear();
  107. ret = false;
  108. }
  109. if (wield_item.length() > U16_MAX) {
  110. warningstream << func << "wield_item has excessive length, clearing it." << std::endl;
  111. wield_item.clear();
  112. ret = false;
  113. }
  114. return ret;
  115. }
  116. void ObjectProperties::serialize(std::ostream &os) const
  117. {
  118. writeU8(os, 4); // PROTOCOL_VERSION >= 37
  119. writeU16(os, hp_max);
  120. writeU8(os, physical);
  121. writeF32(os, 0.f); // Removed property (weight)
  122. writeV3F32(os, collisionbox.MinEdge);
  123. writeV3F32(os, collisionbox.MaxEdge);
  124. writeV3F32(os, selectionbox.MinEdge);
  125. writeV3F32(os, selectionbox.MaxEdge);
  126. Pointabilities::serializePointabilityType(os, pointable);
  127. os << serializeString16(visual);
  128. writeV3F32(os, visual_size);
  129. writeU16(os, textures.size());
  130. for (const std::string &texture : textures) {
  131. os << serializeString16(texture);
  132. }
  133. writeV2S16(os, spritediv);
  134. writeV2S16(os, initial_sprite_basepos);
  135. writeU8(os, is_visible);
  136. writeU8(os, makes_footstep_sound);
  137. writeF32(os, automatic_rotate);
  138. os << serializeString16(mesh);
  139. writeU16(os, colors.size());
  140. for (video::SColor color : colors) {
  141. writeARGB8(os, color);
  142. }
  143. writeU8(os, collideWithObjects);
  144. writeF32(os, stepheight);
  145. writeU8(os, automatic_face_movement_dir);
  146. writeF32(os, automatic_face_movement_dir_offset);
  147. writeU8(os, backface_culling);
  148. os << serializeString16(nametag);
  149. writeARGB8(os, nametag_color);
  150. writeF32(os, automatic_face_movement_max_rotation_per_sec);
  151. os << serializeString16(infotext);
  152. os << serializeString16(wield_item);
  153. writeS8(os, glow);
  154. writeU16(os, breath_max);
  155. writeF32(os, eye_height);
  156. writeF32(os, zoom_fov);
  157. writeU8(os, use_texture_alpha);
  158. os << serializeString16(damage_texture_modifier);
  159. writeU8(os, shaded);
  160. writeU8(os, show_on_minimap);
  161. if (!nametag_bgcolor)
  162. writeARGB8(os, NULL_BGCOLOR);
  163. else if (nametag_bgcolor.value().getAlpha() == 0)
  164. writeARGB8(os, video::SColor(0, 0, 0, 0));
  165. else
  166. writeARGB8(os, nametag_bgcolor.value());
  167. writeU8(os, rotate_selectionbox);
  168. // Add stuff only at the bottom.
  169. // Never remove anything, because we don't want new versions of this
  170. }
  171. void ObjectProperties::deSerialize(std::istream &is)
  172. {
  173. int version = readU8(is);
  174. if (version != 4)
  175. throw SerializationError("unsupported ObjectProperties version");
  176. hp_max = readU16(is);
  177. physical = readU8(is);
  178. readU32(is); // removed property (weight)
  179. collisionbox.MinEdge = readV3F32(is);
  180. collisionbox.MaxEdge = readV3F32(is);
  181. selectionbox.MinEdge = readV3F32(is);
  182. selectionbox.MaxEdge = readV3F32(is);
  183. pointable = Pointabilities::deSerializePointabilityType(is);
  184. visual = deSerializeString16(is);
  185. visual_size = readV3F32(is);
  186. textures.clear();
  187. u32 texture_count = readU16(is);
  188. for (u32 i = 0; i < texture_count; i++){
  189. textures.push_back(deSerializeString16(is));
  190. }
  191. spritediv = readV2S16(is);
  192. initial_sprite_basepos = readV2S16(is);
  193. is_visible = readU8(is);
  194. makes_footstep_sound = readU8(is);
  195. automatic_rotate = readF32(is);
  196. mesh = deSerializeString16(is);
  197. colors.clear();
  198. u32 color_count = readU16(is);
  199. for (u32 i = 0; i < color_count; i++){
  200. colors.push_back(readARGB8(is));
  201. }
  202. collideWithObjects = readU8(is);
  203. stepheight = readF32(is);
  204. automatic_face_movement_dir = readU8(is);
  205. automatic_face_movement_dir_offset = readF32(is);
  206. backface_culling = readU8(is);
  207. nametag = deSerializeString16(is);
  208. nametag_color = readARGB8(is);
  209. automatic_face_movement_max_rotation_per_sec = readF32(is);
  210. infotext = deSerializeString16(is);
  211. wield_item = deSerializeString16(is);
  212. glow = readS8(is);
  213. breath_max = readU16(is);
  214. eye_height = readF32(is);
  215. zoom_fov = readF32(is);
  216. use_texture_alpha = readU8(is);
  217. try {
  218. damage_texture_modifier = deSerializeString16(is);
  219. u8 tmp = readU8(is);
  220. if (is.eof())
  221. return;
  222. shaded = tmp;
  223. tmp = readU8(is);
  224. if (is.eof())
  225. return;
  226. show_on_minimap = tmp;
  227. auto bgcolor = readARGB8(is);
  228. if (bgcolor != NULL_BGCOLOR)
  229. nametag_bgcolor = bgcolor;
  230. else
  231. nametag_bgcolor = std::nullopt;
  232. tmp = readU8(is);
  233. if (is.eof())
  234. return;
  235. rotate_selectionbox = tmp;
  236. } catch (SerializationError &e) {}
  237. }