nodedef.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. /*
  2. Minetest
  3. Copyright (C) 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 "nodedef.h"
  17. #include "main.h" // For g_settings
  18. #include "itemdef.h"
  19. #ifndef SERVER
  20. #include "tile.h"
  21. #endif
  22. #include "log.h"
  23. #include "settings.h"
  24. #include "nameidmapping.h"
  25. #include "util/numeric.h"
  26. #include "util/serialize.h"
  27. //#include "profiler.h" // For TimeTaker
  28. /*
  29. NodeBox
  30. */
  31. void NodeBox::reset()
  32. {
  33. type = NODEBOX_REGULAR;
  34. // default is empty
  35. fixed.clear();
  36. // default is sign/ladder-like
  37. wall_top = aabb3f(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2);
  38. wall_bottom = aabb3f(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2);
  39. wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2);
  40. }
  41. void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
  42. {
  43. int version = protocol_version >= 21 ? 2 : 1;
  44. writeU8(os, version);
  45. if (version == 1 && type == NODEBOX_LEVELED)
  46. writeU8(os, NODEBOX_FIXED);
  47. else
  48. writeU8(os, type);
  49. if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
  50. {
  51. writeU16(os, fixed.size());
  52. for(std::vector<aabb3f>::const_iterator
  53. i = fixed.begin();
  54. i != fixed.end(); i++)
  55. {
  56. writeV3F1000(os, i->MinEdge);
  57. writeV3F1000(os, i->MaxEdge);
  58. }
  59. }
  60. else if(type == NODEBOX_WALLMOUNTED)
  61. {
  62. writeV3F1000(os, wall_top.MinEdge);
  63. writeV3F1000(os, wall_top.MaxEdge);
  64. writeV3F1000(os, wall_bottom.MinEdge);
  65. writeV3F1000(os, wall_bottom.MaxEdge);
  66. writeV3F1000(os, wall_side.MinEdge);
  67. writeV3F1000(os, wall_side.MaxEdge);
  68. }
  69. }
  70. void NodeBox::deSerialize(std::istream &is)
  71. {
  72. int version = readU8(is);
  73. if(version < 1 || version > 2)
  74. throw SerializationError("unsupported NodeBox version");
  75. reset();
  76. type = (enum NodeBoxType)readU8(is);
  77. if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
  78. {
  79. u16 fixed_count = readU16(is);
  80. while(fixed_count--)
  81. {
  82. aabb3f box;
  83. box.MinEdge = readV3F1000(is);
  84. box.MaxEdge = readV3F1000(is);
  85. fixed.push_back(box);
  86. }
  87. }
  88. else if(type == NODEBOX_WALLMOUNTED)
  89. {
  90. wall_top.MinEdge = readV3F1000(is);
  91. wall_top.MaxEdge = readV3F1000(is);
  92. wall_bottom.MinEdge = readV3F1000(is);
  93. wall_bottom.MaxEdge = readV3F1000(is);
  94. wall_side.MinEdge = readV3F1000(is);
  95. wall_side.MaxEdge = readV3F1000(is);
  96. }
  97. }
  98. /*
  99. TileDef
  100. */
  101. void TileDef::serialize(std::ostream &os, u16 protocol_version) const
  102. {
  103. if(protocol_version >= 17)
  104. writeU8(os, 1);
  105. else
  106. writeU8(os, 0);
  107. os<<serializeString(name);
  108. writeU8(os, animation.type);
  109. writeU16(os, animation.aspect_w);
  110. writeU16(os, animation.aspect_h);
  111. writeF1000(os, animation.length);
  112. if(protocol_version >= 17)
  113. writeU8(os, backface_culling);
  114. }
  115. void TileDef::deSerialize(std::istream &is)
  116. {
  117. int version = readU8(is);
  118. name = deSerializeString(is);
  119. animation.type = (TileAnimationType)readU8(is);
  120. animation.aspect_w = readU16(is);
  121. animation.aspect_h = readU16(is);
  122. animation.length = readF1000(is);
  123. if(version >= 1)
  124. backface_culling = readU8(is);
  125. }
  126. /*
  127. SimpleSoundSpec serialization
  128. */
  129. static void serializeSimpleSoundSpec(const SimpleSoundSpec &ss,
  130. std::ostream &os)
  131. {
  132. os<<serializeString(ss.name);
  133. writeF1000(os, ss.gain);
  134. }
  135. static void deSerializeSimpleSoundSpec(SimpleSoundSpec &ss, std::istream &is)
  136. {
  137. ss.name = deSerializeString(is);
  138. ss.gain = readF1000(is);
  139. }
  140. /*
  141. ContentFeatures
  142. */
  143. ContentFeatures::ContentFeatures()
  144. {
  145. reset();
  146. }
  147. ContentFeatures::~ContentFeatures()
  148. {
  149. }
  150. void ContentFeatures::reset()
  151. {
  152. /*
  153. Cached stuff
  154. */
  155. #ifndef SERVER
  156. solidness = 2;
  157. visual_solidness = 0;
  158. backface_culling = true;
  159. #endif
  160. has_on_construct = false;
  161. has_on_destruct = false;
  162. has_after_destruct = false;
  163. /*
  164. Actual data
  165. NOTE: Most of this is always overridden by the default values given
  166. in builtin.lua
  167. */
  168. name = "";
  169. groups.clear();
  170. // Unknown nodes can be dug
  171. groups["dig_immediate"] = 2;
  172. drawtype = NDT_NORMAL;
  173. visual_scale = 1.0;
  174. for(u32 i = 0; i < 6; i++)
  175. tiledef[i] = TileDef();
  176. for(u16 j = 0; j < CF_SPECIAL_COUNT; j++)
  177. tiledef_special[j] = TileDef();
  178. alpha = 255;
  179. post_effect_color = video::SColor(0, 0, 0, 0);
  180. param_type = CPT_NONE;
  181. param_type_2 = CPT2_NONE;
  182. is_ground_content = false;
  183. light_propagates = false;
  184. sunlight_propagates = false;
  185. walkable = true;
  186. pointable = true;
  187. diggable = true;
  188. climbable = false;
  189. buildable_to = false;
  190. rightclickable = true;
  191. leveled = 0;
  192. liquid_type = LIQUID_NONE;
  193. liquid_alternative_flowing = "";
  194. liquid_alternative_source = "";
  195. liquid_viscosity = 0;
  196. liquid_renewable = true;
  197. freezemelt = "";
  198. liquid_range = LIQUID_LEVEL_MAX+1;
  199. drowning = 0;
  200. light_source = 0;
  201. damage_per_second = 0;
  202. node_box = NodeBox();
  203. selection_box = NodeBox();
  204. waving = 0;
  205. legacy_facedir_simple = false;
  206. legacy_wallmounted = false;
  207. sound_footstep = SimpleSoundSpec();
  208. sound_dig = SimpleSoundSpec("__group");
  209. sound_dug = SimpleSoundSpec();
  210. }
  211. void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
  212. {
  213. if(protocol_version < 24){
  214. serializeOld(os, protocol_version);
  215. return;
  216. }
  217. writeU8(os, 7); // version
  218. os<<serializeString(name);
  219. writeU16(os, groups.size());
  220. for(ItemGroupList::const_iterator
  221. i = groups.begin(); i != groups.end(); i++){
  222. os<<serializeString(i->first);
  223. writeS16(os, i->second);
  224. }
  225. writeU8(os, drawtype);
  226. writeF1000(os, visual_scale);
  227. writeU8(os, 6);
  228. for(u32 i = 0; i < 6; i++)
  229. tiledef[i].serialize(os, protocol_version);
  230. writeU8(os, CF_SPECIAL_COUNT);
  231. for(u32 i = 0; i < CF_SPECIAL_COUNT; i++){
  232. tiledef_special[i].serialize(os, protocol_version);
  233. }
  234. writeU8(os, alpha);
  235. writeU8(os, post_effect_color.getAlpha());
  236. writeU8(os, post_effect_color.getRed());
  237. writeU8(os, post_effect_color.getGreen());
  238. writeU8(os, post_effect_color.getBlue());
  239. writeU8(os, param_type);
  240. writeU8(os, param_type_2);
  241. writeU8(os, is_ground_content);
  242. writeU8(os, light_propagates);
  243. writeU8(os, sunlight_propagates);
  244. writeU8(os, walkable);
  245. writeU8(os, pointable);
  246. writeU8(os, diggable);
  247. writeU8(os, climbable);
  248. writeU8(os, buildable_to);
  249. os<<serializeString(""); // legacy: used to be metadata_name
  250. writeU8(os, liquid_type);
  251. os<<serializeString(liquid_alternative_flowing);
  252. os<<serializeString(liquid_alternative_source);
  253. writeU8(os, liquid_viscosity);
  254. writeU8(os, liquid_renewable);
  255. writeU8(os, light_source);
  256. writeU32(os, damage_per_second);
  257. node_box.serialize(os, protocol_version);
  258. selection_box.serialize(os, protocol_version);
  259. writeU8(os, legacy_facedir_simple);
  260. writeU8(os, legacy_wallmounted);
  261. serializeSimpleSoundSpec(sound_footstep, os);
  262. serializeSimpleSoundSpec(sound_dig, os);
  263. serializeSimpleSoundSpec(sound_dug, os);
  264. writeU8(os, rightclickable);
  265. writeU8(os, drowning);
  266. writeU8(os, leveled);
  267. writeU8(os, liquid_range);
  268. writeU8(os, waving);
  269. // Stuff below should be moved to correct place in a version that otherwise changes
  270. // the protocol version
  271. }
  272. void ContentFeatures::deSerialize(std::istream &is)
  273. {
  274. int version = readU8(is);
  275. if(version != 7){
  276. deSerializeOld(is, version);
  277. return;
  278. }
  279. name = deSerializeString(is);
  280. groups.clear();
  281. u32 groups_size = readU16(is);
  282. for(u32 i = 0; i < groups_size; i++){
  283. std::string name = deSerializeString(is);
  284. int value = readS16(is);
  285. groups[name] = value;
  286. }
  287. drawtype = (enum NodeDrawType)readU8(is);
  288. visual_scale = readF1000(is);
  289. if(readU8(is) != 6)
  290. throw SerializationError("unsupported tile count");
  291. for(u32 i = 0; i < 6; i++)
  292. tiledef[i].deSerialize(is);
  293. if(readU8(is) != CF_SPECIAL_COUNT)
  294. throw SerializationError("unsupported CF_SPECIAL_COUNT");
  295. for(u32 i = 0; i < CF_SPECIAL_COUNT; i++)
  296. tiledef_special[i].deSerialize(is);
  297. alpha = readU8(is);
  298. post_effect_color.setAlpha(readU8(is));
  299. post_effect_color.setRed(readU8(is));
  300. post_effect_color.setGreen(readU8(is));
  301. post_effect_color.setBlue(readU8(is));
  302. param_type = (enum ContentParamType)readU8(is);
  303. param_type_2 = (enum ContentParamType2)readU8(is);
  304. is_ground_content = readU8(is);
  305. light_propagates = readU8(is);
  306. sunlight_propagates = readU8(is);
  307. walkable = readU8(is);
  308. pointable = readU8(is);
  309. diggable = readU8(is);
  310. climbable = readU8(is);
  311. buildable_to = readU8(is);
  312. deSerializeString(is); // legacy: used to be metadata_name
  313. liquid_type = (enum LiquidType)readU8(is);
  314. liquid_alternative_flowing = deSerializeString(is);
  315. liquid_alternative_source = deSerializeString(is);
  316. liquid_viscosity = readU8(is);
  317. liquid_renewable = readU8(is);
  318. light_source = readU8(is);
  319. damage_per_second = readU32(is);
  320. node_box.deSerialize(is);
  321. selection_box.deSerialize(is);
  322. legacy_facedir_simple = readU8(is);
  323. legacy_wallmounted = readU8(is);
  324. deSerializeSimpleSoundSpec(sound_footstep, is);
  325. deSerializeSimpleSoundSpec(sound_dig, is);
  326. deSerializeSimpleSoundSpec(sound_dug, is);
  327. rightclickable = readU8(is);
  328. drowning = readU8(is);
  329. leveled = readU8(is);
  330. liquid_range = readU8(is);
  331. waving = readU8(is);
  332. // If you add anything here, insert it primarily inside the try-catch
  333. // block to not need to increase the version.
  334. try{
  335. // Stuff below should be moved to correct place in a version that
  336. // otherwise changes the protocol version
  337. }catch(SerializationError &e) {};
  338. }
  339. /*
  340. CNodeDefManager
  341. */
  342. class CNodeDefManager: public IWritableNodeDefManager
  343. {
  344. public:
  345. void clear()
  346. {
  347. m_content_features.clear();
  348. m_name_id_mapping.clear();
  349. m_name_id_mapping_with_aliases.clear();
  350. m_group_to_items.clear();
  351. m_next_id = 0;
  352. u32 initial_length = 0;
  353. initial_length = MYMAX(initial_length, CONTENT_UNKNOWN + 1);
  354. initial_length = MYMAX(initial_length, CONTENT_AIR + 1);
  355. initial_length = MYMAX(initial_length, CONTENT_IGNORE + 1);
  356. m_content_features.resize(initial_length);
  357. // Set CONTENT_UNKNOWN
  358. {
  359. ContentFeatures f;
  360. f.name = "unknown";
  361. // Insert directly into containers
  362. content_t c = CONTENT_UNKNOWN;
  363. m_content_features[c] = f;
  364. addNameIdMapping(c, f.name);
  365. }
  366. // Set CONTENT_AIR
  367. {
  368. ContentFeatures f;
  369. f.name = "air";
  370. f.drawtype = NDT_AIRLIKE;
  371. f.param_type = CPT_LIGHT;
  372. f.light_propagates = true;
  373. f.sunlight_propagates = true;
  374. f.walkable = false;
  375. f.pointable = false;
  376. f.diggable = false;
  377. f.buildable_to = true;
  378. f.is_ground_content = true;
  379. // Insert directly into containers
  380. content_t c = CONTENT_AIR;
  381. m_content_features[c] = f;
  382. addNameIdMapping(c, f.name);
  383. }
  384. // Set CONTENT_IGNORE
  385. {
  386. ContentFeatures f;
  387. f.name = "ignore";
  388. f.drawtype = NDT_AIRLIKE;
  389. f.param_type = CPT_NONE;
  390. f.light_propagates = false;
  391. f.sunlight_propagates = false;
  392. f.walkable = false;
  393. f.pointable = false;
  394. f.diggable = false;
  395. f.buildable_to = true; // A way to remove accidental CONTENT_IGNOREs
  396. f.is_ground_content = true;
  397. // Insert directly into containers
  398. content_t c = CONTENT_IGNORE;
  399. m_content_features[c] = f;
  400. addNameIdMapping(c, f.name);
  401. }
  402. }
  403. CNodeDefManager()
  404. {
  405. clear();
  406. }
  407. virtual ~CNodeDefManager()
  408. {
  409. }
  410. virtual IWritableNodeDefManager* clone()
  411. {
  412. CNodeDefManager *mgr = new CNodeDefManager();
  413. *mgr = *this;
  414. return mgr;
  415. }
  416. virtual const ContentFeatures& get(content_t c) const
  417. {
  418. if(c < m_content_features.size())
  419. return m_content_features[c];
  420. else
  421. return m_content_features[CONTENT_UNKNOWN];
  422. }
  423. virtual const ContentFeatures& get(const MapNode &n) const
  424. {
  425. return get(n.getContent());
  426. }
  427. virtual bool getId(const std::string &name, content_t &result) const
  428. {
  429. std::map<std::string, content_t>::const_iterator
  430. i = m_name_id_mapping_with_aliases.find(name);
  431. if(i == m_name_id_mapping_with_aliases.end())
  432. return false;
  433. result = i->second;
  434. return true;
  435. }
  436. virtual content_t getId(const std::string &name) const
  437. {
  438. content_t id = CONTENT_IGNORE;
  439. getId(name, id);
  440. return id;
  441. }
  442. virtual void getIds(const std::string &name, std::set<content_t> &result)
  443. const
  444. {
  445. //TimeTaker t("getIds", NULL, PRECISION_MICRO);
  446. if(name.substr(0,6) != "group:"){
  447. content_t id = CONTENT_IGNORE;
  448. if(getId(name, id))
  449. result.insert(id);
  450. return;
  451. }
  452. std::string group = name.substr(6);
  453. std::map<std::string, GroupItems>::const_iterator
  454. i = m_group_to_items.find(group);
  455. if (i == m_group_to_items.end())
  456. return;
  457. const GroupItems &items = i->second;
  458. for (GroupItems::const_iterator j = items.begin();
  459. j != items.end(); ++j) {
  460. if ((*j).second != 0)
  461. result.insert((*j).first);
  462. }
  463. //printf("getIds: %dus\n", t.stop());
  464. }
  465. virtual const ContentFeatures& get(const std::string &name) const
  466. {
  467. content_t id = CONTENT_UNKNOWN;
  468. getId(name, id);
  469. return get(id);
  470. }
  471. // returns CONTENT_IGNORE if no free ID found
  472. content_t allocateId()
  473. {
  474. for(content_t id = m_next_id;
  475. id >= m_next_id; // overflow?
  476. ++id){
  477. while(id >= m_content_features.size()){
  478. m_content_features.push_back(ContentFeatures());
  479. }
  480. const ContentFeatures &f = m_content_features[id];
  481. if(f.name == ""){
  482. m_next_id = id + 1;
  483. return id;
  484. }
  485. }
  486. // If we arrive here, an overflow occurred in id.
  487. // That means no ID was found
  488. return CONTENT_IGNORE;
  489. }
  490. // IWritableNodeDefManager
  491. virtual content_t set(const std::string &name,
  492. const ContentFeatures &def)
  493. {
  494. assert(name != "");
  495. assert(name == def.name);
  496. // Don't allow redefining ignore (but allow air and unknown)
  497. if(name == "ignore"){
  498. infostream<<"NodeDefManager: WARNING: Ignoring "
  499. <<"CONTENT_IGNORE redefinition"<<std::endl;
  500. return CONTENT_IGNORE;
  501. }
  502. content_t id = CONTENT_IGNORE;
  503. bool found = m_name_id_mapping.getId(name, id); // ignore aliases
  504. if(!found){
  505. // Get new id
  506. id = allocateId();
  507. if(id == CONTENT_IGNORE){
  508. infostream<<"NodeDefManager: WARNING: Absolute "
  509. <<"limit reached"<<std::endl;
  510. return CONTENT_IGNORE;
  511. }
  512. assert(id != CONTENT_IGNORE);
  513. addNameIdMapping(id, name);
  514. }
  515. m_content_features[id] = def;
  516. verbosestream<<"NodeDefManager: registering content id \""<<id
  517. <<"\": name=\""<<def.name<<"\""<<std::endl;
  518. // Add this content to the list of all groups it belongs to
  519. // FIXME: This should remove a node from groups it no longer
  520. // belongs to when a node is re-registered
  521. for (ItemGroupList::const_iterator i = def.groups.begin();
  522. i != def.groups.end(); ++i) {
  523. std::string group_name = i->first;
  524. std::map<std::string, GroupItems>::iterator
  525. j = m_group_to_items.find(group_name);
  526. if (j == m_group_to_items.end()) {
  527. m_group_to_items[group_name].push_back(
  528. std::make_pair(id, i->second));
  529. } else {
  530. GroupItems &items = j->second;
  531. items.push_back(std::make_pair(id, i->second));
  532. }
  533. }
  534. return id;
  535. }
  536. virtual content_t allocateDummy(const std::string &name)
  537. {
  538. assert(name != "");
  539. ContentFeatures f;
  540. f.name = name;
  541. return set(name, f);
  542. }
  543. virtual void updateAliases(IItemDefManager *idef)
  544. {
  545. std::set<std::string> all = idef->getAll();
  546. m_name_id_mapping_with_aliases.clear();
  547. for(std::set<std::string>::iterator
  548. i = all.begin(); i != all.end(); i++)
  549. {
  550. std::string name = *i;
  551. std::string convert_to = idef->getAlias(name);
  552. content_t id;
  553. if(m_name_id_mapping.getId(convert_to, id))
  554. {
  555. m_name_id_mapping_with_aliases.insert(
  556. std::make_pair(name, id));
  557. }
  558. }
  559. }
  560. virtual void updateTextures(ITextureSource *tsrc,
  561. IShaderSource *shdsrc)
  562. {
  563. #ifndef SERVER
  564. infostream<<"CNodeDefManager::updateTextures(): Updating "
  565. <<"textures in node definitions"<<std::endl;
  566. bool new_style_water = g_settings->getBool("new_style_water");
  567. bool new_style_leaves = g_settings->getBool("new_style_leaves");
  568. bool opaque_water = g_settings->getBool("opaque_water");
  569. bool enable_shaders = g_settings->getBool("enable_shaders");
  570. bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping");
  571. bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion");
  572. for(u32 i=0; i<m_content_features.size(); i++)
  573. {
  574. ContentFeatures *f = &m_content_features[i];
  575. // Figure out the actual tiles to use
  576. TileDef tiledef[6];
  577. for(u32 j = 0; j < 6; j++)
  578. {
  579. tiledef[j] = f->tiledef[j];
  580. if(tiledef[j].name == "")
  581. tiledef[j].name = "unknown_node.png";
  582. }
  583. bool is_liquid = false;
  584. bool is_water_surface = false;
  585. u8 material_type;
  586. material_type = (f->alpha == 255) ? TILE_MATERIAL_BASIC : TILE_MATERIAL_ALPHA;
  587. switch(f->drawtype){
  588. default:
  589. case NDT_NORMAL:
  590. f->solidness = 2;
  591. break;
  592. case NDT_AIRLIKE:
  593. f->solidness = 0;
  594. break;
  595. case NDT_LIQUID:
  596. assert(f->liquid_type == LIQUID_SOURCE);
  597. if(opaque_water)
  598. f->alpha = 255;
  599. if(new_style_water){
  600. f->solidness = 0;
  601. } else {
  602. f->solidness = 1;
  603. f->backface_culling = false;
  604. }
  605. is_liquid = true;
  606. break;
  607. case NDT_FLOWINGLIQUID:
  608. assert(f->liquid_type == LIQUID_FLOWING);
  609. f->solidness = 0;
  610. if(opaque_water)
  611. f->alpha = 255;
  612. is_liquid = true;
  613. break;
  614. case NDT_GLASSLIKE:
  615. f->solidness = 0;
  616. f->visual_solidness = 1;
  617. break;
  618. case NDT_GLASSLIKE_FRAMED:
  619. f->solidness = 0;
  620. f->visual_solidness = 1;
  621. break;
  622. case NDT_ALLFACES:
  623. f->solidness = 0;
  624. f->visual_solidness = 1;
  625. break;
  626. case NDT_ALLFACES_OPTIONAL:
  627. if(new_style_leaves){
  628. f->drawtype = NDT_ALLFACES;
  629. f->solidness = 0;
  630. f->visual_solidness = 1;
  631. } else {
  632. f->drawtype = NDT_NORMAL;
  633. f->solidness = 2;
  634. for(u32 i=0; i<6; i++){
  635. tiledef[i].name += std::string("^[noalpha");
  636. }
  637. }
  638. if (f->waving == 1)
  639. material_type = TILE_MATERIAL_WAVING_LEAVES;
  640. break;
  641. case NDT_PLANTLIKE:
  642. f->solidness = 0;
  643. f->backface_culling = false;
  644. if (f->waving == 1)
  645. material_type = TILE_MATERIAL_WAVING_PLANTS;
  646. break;
  647. case NDT_TORCHLIKE:
  648. case NDT_SIGNLIKE:
  649. case NDT_FENCELIKE:
  650. case NDT_RAILLIKE:
  651. case NDT_NODEBOX:
  652. f->solidness = 0;
  653. break;
  654. }
  655. if (is_liquid){
  656. material_type = (f->alpha == 255) ? TILE_MATERIAL_LIQUID_OPAQUE : TILE_MATERIAL_LIQUID_TRANSPARENT;
  657. if (f->name == "default:water_source")
  658. is_water_surface = true;
  659. }
  660. u32 tile_shader[6];
  661. for(u16 j=0; j<6; j++)
  662. tile_shader[j] = shdsrc->getShader("nodes_shader",material_type, f->drawtype);
  663. if (is_water_surface)
  664. tile_shader[0] = shdsrc->getShader("water_surface_shader",material_type, f->drawtype);
  665. // Tiles (fill in f->tiles[])
  666. for(u16 j = 0; j < 6; j++){
  667. // Shader
  668. f->tiles[j].shader_id = tile_shader[j];
  669. // Texture
  670. f->tiles[j].texture = tsrc->getTexture(
  671. tiledef[j].name,
  672. &f->tiles[j].texture_id);
  673. // Normal texture
  674. if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
  675. f->tiles[j].normal_texture = tsrc->getNormalTexture(tiledef[j].name);
  676. // Alpha
  677. f->tiles[j].alpha = f->alpha;
  678. // Material type
  679. f->tiles[j].material_type = material_type;
  680. // Material flags
  681. f->tiles[j].material_flags = 0;
  682. if(f->backface_culling)
  683. f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
  684. if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES)
  685. f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
  686. // Animation parameters
  687. int frame_count = 1;
  688. if(f->tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
  689. // Get texture size to determine frame count by
  690. // aspect ratio
  691. v2u32 size = f->tiles[j].texture->getOriginalSize();
  692. int frame_height = (float)size.X /
  693. (float)tiledef[j].animation.aspect_w *
  694. (float)tiledef[j].animation.aspect_h;
  695. frame_count = size.Y / frame_height;
  696. int frame_length_ms = 1000.0 *
  697. tiledef[j].animation.length / frame_count;
  698. f->tiles[j].animation_frame_count = frame_count;
  699. f->tiles[j].animation_frame_length_ms = frame_length_ms;
  700. }
  701. if(frame_count == 1) {
  702. f->tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
  703. } else {
  704. std::ostringstream os(std::ios::binary);
  705. for (int i = 0; i < frame_count; i++) {
  706. FrameSpec frame;
  707. os.str("");
  708. os<<tiledef[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
  709. frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
  710. if (f->tiles[j].normal_texture)
  711. frame.normal_texture = tsrc->getNormalTexture(os.str());
  712. f->tiles[j].frames[i]=frame;
  713. }
  714. }
  715. }
  716. // Special tiles (fill in f->special_tiles[])
  717. for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
  718. // Shader
  719. f->special_tiles[j].shader_id = tile_shader[j];
  720. // Texture
  721. f->special_tiles[j].texture = tsrc->getTexture(
  722. f->tiledef_special[j].name,
  723. &f->special_tiles[j].texture_id);
  724. // Normal texture
  725. if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion))
  726. f->special_tiles[j].normal_texture = tsrc->getNormalTexture(f->tiledef_special[j].name);
  727. // Alpha
  728. f->special_tiles[j].alpha = f->alpha;
  729. // Material type
  730. f->special_tiles[j].material_type = material_type;
  731. // Material flags
  732. f->special_tiles[j].material_flags = 0;
  733. if(f->tiledef_special[j].backface_culling)
  734. f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
  735. if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES)
  736. f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
  737. // Animation parameters
  738. int frame_count = 1;
  739. if(f->special_tiles[j].material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) {
  740. // Get texture size to determine frame count by
  741. // aspect ratio
  742. v2u32 size = f->special_tiles[j].texture->getOriginalSize();
  743. int frame_height = (float)size.X /
  744. (float)f->tiledef_special[j].animation.aspect_w *
  745. (float)f->tiledef_special[j].animation.aspect_h;
  746. frame_count = size.Y / frame_height;
  747. int frame_length_ms = 1000.0 *
  748. f->tiledef_special[j].animation.length / frame_count;
  749. f->special_tiles[j].animation_frame_count = frame_count;
  750. f->special_tiles[j].animation_frame_length_ms = frame_length_ms;
  751. }
  752. if(frame_count == 1) {
  753. f->special_tiles[j].material_flags &= ~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
  754. } else {
  755. std::ostringstream os(std::ios::binary);
  756. for (int i = 0; i < frame_count; i++) {
  757. FrameSpec frame;
  758. os.str("");
  759. os<<f->tiledef_special[j].name<<"^[verticalframe:"<<frame_count<<":"<<i;
  760. frame.texture = tsrc->getTexture(os.str(), &frame.texture_id);
  761. if (f->special_tiles[j].normal_texture)
  762. frame.normal_texture = tsrc->getNormalTexture(os.str());
  763. f->special_tiles[j].frames[i]=frame;
  764. }
  765. }
  766. }
  767. }
  768. #endif
  769. }
  770. void serialize(std::ostream &os, u16 protocol_version)
  771. {
  772. writeU8(os, 1); // version
  773. u16 count = 0;
  774. std::ostringstream os2(std::ios::binary);
  775. for(u32 i = 0; i < m_content_features.size(); i++)
  776. {
  777. if(i == CONTENT_IGNORE || i == CONTENT_AIR
  778. || i == CONTENT_UNKNOWN)
  779. continue;
  780. ContentFeatures *f = &m_content_features[i];
  781. if(f->name == "")
  782. continue;
  783. writeU16(os2, i);
  784. // Wrap it in a string to allow different lengths without
  785. // strict version incompatibilities
  786. std::ostringstream wrapper_os(std::ios::binary);
  787. f->serialize(wrapper_os, protocol_version);
  788. os2<<serializeString(wrapper_os.str());
  789. assert(count + 1 > count); // must not overflow
  790. count++;
  791. }
  792. writeU16(os, count);
  793. os<<serializeLongString(os2.str());
  794. }
  795. void deSerialize(std::istream &is)
  796. {
  797. clear();
  798. int version = readU8(is);
  799. if(version != 1)
  800. throw SerializationError("unsupported NodeDefinitionManager version");
  801. u16 count = readU16(is);
  802. std::istringstream is2(deSerializeLongString(is), std::ios::binary);
  803. ContentFeatures f;
  804. for(u16 n = 0; n < count; n++){
  805. u16 i = readU16(is2);
  806. // Read it from the string wrapper
  807. std::string wrapper = deSerializeString(is2);
  808. std::istringstream wrapper_is(wrapper, std::ios::binary);
  809. f.deSerialize(wrapper_is);
  810. // Check error conditions
  811. if(i == CONTENT_IGNORE || i == CONTENT_AIR
  812. || i == CONTENT_UNKNOWN){
  813. infostream<<"NodeDefManager::deSerialize(): WARNING: "
  814. <<"not changing builtin node "<<i
  815. <<std::endl;
  816. continue;
  817. }
  818. if(f.name == ""){
  819. infostream<<"NodeDefManager::deSerialize(): WARNING: "
  820. <<"received empty name"<<std::endl;
  821. continue;
  822. }
  823. u16 existing_id;
  824. bool found = m_name_id_mapping.getId(f.name, existing_id); // ignore aliases
  825. if(found && i != existing_id){
  826. infostream<<"NodeDefManager::deSerialize(): WARNING: "
  827. <<"already defined with different ID: "
  828. <<f.name<<std::endl;
  829. continue;
  830. }
  831. // All is ok, add node definition with the requested ID
  832. if(i >= m_content_features.size())
  833. m_content_features.resize((u32)(i) + 1);
  834. m_content_features[i] = f;
  835. addNameIdMapping(i, f.name);
  836. verbosestream<<"deserialized "<<f.name<<std::endl;
  837. }
  838. }
  839. private:
  840. void addNameIdMapping(content_t i, std::string name)
  841. {
  842. m_name_id_mapping.set(i, name);
  843. m_name_id_mapping_with_aliases.insert(std::make_pair(name, i));
  844. }
  845. private:
  846. // Features indexed by id
  847. std::vector<ContentFeatures> m_content_features;
  848. // A mapping for fast converting back and forth between names and ids
  849. NameIdMapping m_name_id_mapping;
  850. // Like m_name_id_mapping, but only from names to ids, and includes
  851. // item aliases too. Updated by updateAliases()
  852. // Note: Not serialized.
  853. std::map<std::string, content_t> m_name_id_mapping_with_aliases;
  854. // A mapping from groups to a list of content_ts (and their levels)
  855. // that belong to it. Necessary for a direct lookup in getIds().
  856. // Note: Not serialized.
  857. std::map<std::string, GroupItems> m_group_to_items;
  858. // Next possibly free id
  859. content_t m_next_id;
  860. };
  861. IWritableNodeDefManager* createNodeDefManager()
  862. {
  863. return new CNodeDefManager();
  864. }
  865. /*
  866. Serialization of old ContentFeatures formats
  867. */
  868. void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
  869. {
  870. if(protocol_version == 13)
  871. {
  872. writeU8(os, 5); // version
  873. os<<serializeString(name);
  874. writeU16(os, groups.size());
  875. for(ItemGroupList::const_iterator
  876. i = groups.begin(); i != groups.end(); i++){
  877. os<<serializeString(i->first);
  878. writeS16(os, i->second);
  879. }
  880. writeU8(os, drawtype);
  881. writeF1000(os, visual_scale);
  882. writeU8(os, 6);
  883. for(u32 i = 0; i < 6; i++)
  884. tiledef[i].serialize(os, protocol_version);
  885. //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
  886. writeU8(os, 2);
  887. for(u32 i = 0; i < 2; i++){
  888. tiledef_special[i].serialize(os, protocol_version);
  889. }
  890. writeU8(os, alpha);
  891. writeU8(os, post_effect_color.getAlpha());
  892. writeU8(os, post_effect_color.getRed());
  893. writeU8(os, post_effect_color.getGreen());
  894. writeU8(os, post_effect_color.getBlue());
  895. writeU8(os, param_type);
  896. writeU8(os, param_type_2);
  897. writeU8(os, is_ground_content);
  898. writeU8(os, light_propagates);
  899. writeU8(os, sunlight_propagates);
  900. writeU8(os, walkable);
  901. writeU8(os, pointable);
  902. writeU8(os, diggable);
  903. writeU8(os, climbable);
  904. writeU8(os, buildable_to);
  905. os<<serializeString(""); // legacy: used to be metadata_name
  906. writeU8(os, liquid_type);
  907. os<<serializeString(liquid_alternative_flowing);
  908. os<<serializeString(liquid_alternative_source);
  909. writeU8(os, liquid_viscosity);
  910. writeU8(os, light_source);
  911. writeU32(os, damage_per_second);
  912. node_box.serialize(os, protocol_version);
  913. selection_box.serialize(os, protocol_version);
  914. writeU8(os, legacy_facedir_simple);
  915. writeU8(os, legacy_wallmounted);
  916. serializeSimpleSoundSpec(sound_footstep, os);
  917. serializeSimpleSoundSpec(sound_dig, os);
  918. serializeSimpleSoundSpec(sound_dug, os);
  919. }
  920. else if (protocol_version > 13 && protocol_version < 24) {
  921. writeU8(os, 6); // version
  922. os<<serializeString(name);
  923. writeU16(os, groups.size());
  924. for(ItemGroupList::const_iterator
  925. i = groups.begin(); i != groups.end(); i++){
  926. os<<serializeString(i->first);
  927. writeS16(os, i->second);
  928. }
  929. writeU8(os, drawtype);
  930. writeF1000(os, visual_scale);
  931. writeU8(os, 6);
  932. for(u32 i = 0; i < 6; i++)
  933. tiledef[i].serialize(os, protocol_version);
  934. //CF_SPECIAL_COUNT = 2 before cf ver. 7 and protocol ver. 24
  935. writeU8(os, 2);
  936. for(u32 i = 0; i < 2; i++){
  937. tiledef_special[i].serialize(os, protocol_version);
  938. }
  939. writeU8(os, alpha);
  940. writeU8(os, post_effect_color.getAlpha());
  941. writeU8(os, post_effect_color.getRed());
  942. writeU8(os, post_effect_color.getGreen());
  943. writeU8(os, post_effect_color.getBlue());
  944. writeU8(os, param_type);
  945. writeU8(os, param_type_2);
  946. writeU8(os, is_ground_content);
  947. writeU8(os, light_propagates);
  948. writeU8(os, sunlight_propagates);
  949. writeU8(os, walkable);
  950. writeU8(os, pointable);
  951. writeU8(os, diggable);
  952. writeU8(os, climbable);
  953. writeU8(os, buildable_to);
  954. os<<serializeString(""); // legacy: used to be metadata_name
  955. writeU8(os, liquid_type);
  956. os<<serializeString(liquid_alternative_flowing);
  957. os<<serializeString(liquid_alternative_source);
  958. writeU8(os, liquid_viscosity);
  959. writeU8(os, liquid_renewable);
  960. writeU8(os, light_source);
  961. writeU32(os, damage_per_second);
  962. node_box.serialize(os, protocol_version);
  963. selection_box.serialize(os, protocol_version);
  964. writeU8(os, legacy_facedir_simple);
  965. writeU8(os, legacy_wallmounted);
  966. serializeSimpleSoundSpec(sound_footstep, os);
  967. serializeSimpleSoundSpec(sound_dig, os);
  968. serializeSimpleSoundSpec(sound_dug, os);
  969. writeU8(os, rightclickable);
  970. writeU8(os, drowning);
  971. writeU8(os, leveled);
  972. writeU8(os, liquid_range);
  973. } else
  974. throw SerializationError("ContentFeatures::serialize(): Unsupported version requested");
  975. }
  976. void ContentFeatures::deSerializeOld(std::istream &is, int version)
  977. {
  978. if(version == 5) // In PROTOCOL_VERSION 13
  979. {
  980. name = deSerializeString(is);
  981. groups.clear();
  982. u32 groups_size = readU16(is);
  983. for(u32 i=0; i<groups_size; i++){
  984. std::string name = deSerializeString(is);
  985. int value = readS16(is);
  986. groups[name] = value;
  987. }
  988. drawtype = (enum NodeDrawType)readU8(is);
  989. visual_scale = readF1000(is);
  990. if(readU8(is) != 6)
  991. throw SerializationError("unsupported tile count");
  992. for(u32 i=0; i<6; i++)
  993. tiledef[i].deSerialize(is);
  994. if(readU8(is) != CF_SPECIAL_COUNT)
  995. throw SerializationError("unsupported CF_SPECIAL_COUNT");
  996. for(u32 i=0; i<CF_SPECIAL_COUNT; i++)
  997. tiledef_special[i].deSerialize(is);
  998. alpha = readU8(is);
  999. post_effect_color.setAlpha(readU8(is));
  1000. post_effect_color.setRed(readU8(is));
  1001. post_effect_color.setGreen(readU8(is));
  1002. post_effect_color.setBlue(readU8(is));
  1003. param_type = (enum ContentParamType)readU8(is);
  1004. param_type_2 = (enum ContentParamType2)readU8(is);
  1005. is_ground_content = readU8(is);
  1006. light_propagates = readU8(is);
  1007. sunlight_propagates = readU8(is);
  1008. walkable = readU8(is);
  1009. pointable = readU8(is);
  1010. diggable = readU8(is);
  1011. climbable = readU8(is);
  1012. buildable_to = readU8(is);
  1013. deSerializeString(is); // legacy: used to be metadata_name
  1014. liquid_type = (enum LiquidType)readU8(is);
  1015. liquid_alternative_flowing = deSerializeString(is);
  1016. liquid_alternative_source = deSerializeString(is);
  1017. liquid_viscosity = readU8(is);
  1018. light_source = readU8(is);
  1019. damage_per_second = readU32(is);
  1020. node_box.deSerialize(is);
  1021. selection_box.deSerialize(is);
  1022. legacy_facedir_simple = readU8(is);
  1023. legacy_wallmounted = readU8(is);
  1024. deSerializeSimpleSoundSpec(sound_footstep, is);
  1025. deSerializeSimpleSoundSpec(sound_dig, is);
  1026. deSerializeSimpleSoundSpec(sound_dug, is);
  1027. } else if (version == 6) {
  1028. name = deSerializeString(is);
  1029. groups.clear();
  1030. u32 groups_size = readU16(is);
  1031. for(u32 i=0; i<groups_size; i++){
  1032. std::string name = deSerializeString(is);
  1033. int value = readS16(is);
  1034. groups[name] = value;
  1035. }
  1036. drawtype = (enum NodeDrawType)readU8(is);
  1037. visual_scale = readF1000(is);
  1038. if(readU8(is) != 6)
  1039. throw SerializationError("unsupported tile count");
  1040. for(u32 i=0; i<6; i++)
  1041. tiledef[i].deSerialize(is);
  1042. // CF_SPECIAL_COUNT in version 6 = 2
  1043. if(readU8(is) != 2)
  1044. throw SerializationError("unsupported CF_SPECIAL_COUNT");
  1045. for(u32 i=0; i<2; i++)
  1046. tiledef_special[i].deSerialize(is);
  1047. alpha = readU8(is);
  1048. post_effect_color.setAlpha(readU8(is));
  1049. post_effect_color.setRed(readU8(is));
  1050. post_effect_color.setGreen(readU8(is));
  1051. post_effect_color.setBlue(readU8(is));
  1052. param_type = (enum ContentParamType)readU8(is);
  1053. param_type_2 = (enum ContentParamType2)readU8(is);
  1054. is_ground_content = readU8(is);
  1055. light_propagates = readU8(is);
  1056. sunlight_propagates = readU8(is);
  1057. walkable = readU8(is);
  1058. pointable = readU8(is);
  1059. diggable = readU8(is);
  1060. climbable = readU8(is);
  1061. buildable_to = readU8(is);
  1062. deSerializeString(is); // legacy: used to be metadata_name
  1063. liquid_type = (enum LiquidType)readU8(is);
  1064. liquid_alternative_flowing = deSerializeString(is);
  1065. liquid_alternative_source = deSerializeString(is);
  1066. liquid_viscosity = readU8(is);
  1067. liquid_renewable = readU8(is);
  1068. light_source = readU8(is);
  1069. damage_per_second = readU32(is);
  1070. node_box.deSerialize(is);
  1071. selection_box.deSerialize(is);
  1072. legacy_facedir_simple = readU8(is);
  1073. legacy_wallmounted = readU8(is);
  1074. deSerializeSimpleSoundSpec(sound_footstep, is);
  1075. deSerializeSimpleSoundSpec(sound_dig, is);
  1076. deSerializeSimpleSoundSpec(sound_dug, is);
  1077. rightclickable = readU8(is);
  1078. drowning = readU8(is);
  1079. leveled = readU8(is);
  1080. liquid_range = readU8(is);
  1081. } else
  1082. throw SerializationError("unsupported ContentFeatures version");
  1083. }