mapnode.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  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 "irrlichttypes_extrabloated.h"
  17. #include "mapnode.h"
  18. #include "porting.h"
  19. #include "nodedef.h"
  20. #include "map.h"
  21. #include "content_mapnode.h" // For mapnode_translate_*_internal
  22. #include "serialization.h" // For ser_ver_supported
  23. #include "util/serialize.h"
  24. #include "log.h"
  25. #include "util/directiontables.h"
  26. #include "util/numeric.h"
  27. #include <string>
  28. #include <sstream>
  29. static const Rotation wallmounted_to_rot[] = {
  30. ROTATE_0, ROTATE_180, ROTATE_90, ROTATE_270
  31. };
  32. static const u8 rot_to_wallmounted[] = {
  33. 2, 4, 3, 5
  34. };
  35. /*
  36. MapNode
  37. */
  38. // Create directly from a nodename
  39. // If name is unknown, sets CONTENT_IGNORE
  40. MapNode::MapNode(const NodeDefManager *ndef, const std::string &name,
  41. u8 a_param1, u8 a_param2)
  42. {
  43. content_t id = CONTENT_IGNORE;
  44. ndef->getId(name, id);
  45. param0 = id;
  46. param1 = a_param1;
  47. param2 = a_param2;
  48. }
  49. void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const
  50. {
  51. if (f.palette) {
  52. *color = (*f.palette)[param2];
  53. return;
  54. }
  55. *color = f.color;
  56. }
  57. void MapNode::setLight(enum LightBank bank, u8 a_light, const ContentFeatures &f)
  58. {
  59. // If node doesn't contain light data, ignore this
  60. if(f.param_type != CPT_LIGHT)
  61. return;
  62. if(bank == LIGHTBANK_DAY)
  63. {
  64. param1 &= 0xf0;
  65. param1 |= a_light & 0x0f;
  66. }
  67. else if(bank == LIGHTBANK_NIGHT)
  68. {
  69. param1 &= 0x0f;
  70. param1 |= (a_light & 0x0f)<<4;
  71. }
  72. else
  73. assert("Invalid light bank" == NULL);
  74. }
  75. void MapNode::setLight(enum LightBank bank, u8 a_light,
  76. const NodeDefManager *nodemgr)
  77. {
  78. setLight(bank, a_light, nodemgr->get(*this));
  79. }
  80. bool MapNode::isLightDayNightEq(const NodeDefManager *nodemgr) const
  81. {
  82. const ContentFeatures &f = nodemgr->get(*this);
  83. bool isEqual;
  84. if (f.param_type == CPT_LIGHT) {
  85. u8 day = MYMAX(f.light_source, param1 & 0x0f);
  86. u8 night = MYMAX(f.light_source, (param1 >> 4) & 0x0f);
  87. isEqual = day == night;
  88. } else {
  89. isEqual = true;
  90. }
  91. return isEqual;
  92. }
  93. u8 MapNode::getLight(enum LightBank bank, const NodeDefManager *nodemgr) const
  94. {
  95. // Select the brightest of [light source, propagated light]
  96. const ContentFeatures &f = nodemgr->get(*this);
  97. u8 light;
  98. if(f.param_type == CPT_LIGHT)
  99. light = bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
  100. else
  101. light = 0;
  102. return MYMAX(f.light_source, light);
  103. }
  104. u8 MapNode::getLightRaw(enum LightBank bank, const ContentFeatures &f) const
  105. {
  106. if(f.param_type == CPT_LIGHT)
  107. return bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f;
  108. return 0;
  109. }
  110. u8 MapNode::getLightNoChecks(enum LightBank bank, const ContentFeatures *f) const
  111. {
  112. return MYMAX(f->light_source,
  113. bank == LIGHTBANK_DAY ? param1 & 0x0f : (param1 >> 4) & 0x0f);
  114. }
  115. bool MapNode::getLightBanks(u8 &lightday, u8 &lightnight,
  116. const NodeDefManager *nodemgr) const
  117. {
  118. // Select the brightest of [light source, propagated light]
  119. const ContentFeatures &f = nodemgr->get(*this);
  120. if(f.param_type == CPT_LIGHT)
  121. {
  122. lightday = param1 & 0x0f;
  123. lightnight = (param1>>4)&0x0f;
  124. }
  125. else
  126. {
  127. lightday = 0;
  128. lightnight = 0;
  129. }
  130. if(f.light_source > lightday)
  131. lightday = f.light_source;
  132. if(f.light_source > lightnight)
  133. lightnight = f.light_source;
  134. return f.param_type == CPT_LIGHT || f.light_source != 0;
  135. }
  136. u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
  137. bool allow_wallmounted) const
  138. {
  139. const ContentFeatures &f = nodemgr->get(*this);
  140. if (f.param_type_2 == CPT2_FACEDIR ||
  141. f.param_type_2 == CPT2_COLORED_FACEDIR)
  142. return (getParam2() & 0x1F) % 24;
  143. if (allow_wallmounted && (f.param_type_2 == CPT2_WALLMOUNTED ||
  144. f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
  145. return wallmounted_to_facedir[getParam2() & 0x07];
  146. return 0;
  147. }
  148. u8 MapNode::getWallMounted(const NodeDefManager *nodemgr) const
  149. {
  150. const ContentFeatures &f = nodemgr->get(*this);
  151. if (f.param_type_2 == CPT2_WALLMOUNTED ||
  152. f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
  153. return getParam2() & 0x07;
  154. return 0;
  155. }
  156. v3s16 MapNode::getWallMountedDir(const NodeDefManager *nodemgr) const
  157. {
  158. switch(getWallMounted(nodemgr))
  159. {
  160. case 0: default: return v3s16(0,1,0);
  161. case 1: return v3s16(0,-1,0);
  162. case 2: return v3s16(1,0,0);
  163. case 3: return v3s16(-1,0,0);
  164. case 4: return v3s16(0,0,1);
  165. case 5: return v3s16(0,0,-1);
  166. }
  167. }
  168. void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
  169. {
  170. ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
  171. if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR) {
  172. static const u8 rotate_facedir[24 * 4] = {
  173. // Table value = rotated facedir
  174. // Columns: 0, 90, 180, 270 degrees rotation around vertical axis
  175. // Rotation is anticlockwise as seen from above (+Y)
  176. 0, 1, 2, 3, // Initial facedir 0 to 3
  177. 1, 2, 3, 0,
  178. 2, 3, 0, 1,
  179. 3, 0, 1, 2,
  180. 4, 13, 10, 19, // 4 to 7
  181. 5, 14, 11, 16,
  182. 6, 15, 8, 17,
  183. 7, 12, 9, 18,
  184. 8, 17, 6, 15, // 8 to 11
  185. 9, 18, 7, 12,
  186. 10, 19, 4, 13,
  187. 11, 16, 5, 14,
  188. 12, 9, 18, 7, // 12 to 15
  189. 13, 10, 19, 4,
  190. 14, 11, 16, 5,
  191. 15, 8, 17, 6,
  192. 16, 5, 14, 11, // 16 to 19
  193. 17, 6, 15, 8,
  194. 18, 7, 12, 9,
  195. 19, 4, 13, 10,
  196. 20, 23, 22, 21, // 20 to 23
  197. 21, 20, 23, 22,
  198. 22, 21, 20, 23,
  199. 23, 22, 21, 20
  200. };
  201. u8 facedir = (param2 & 31) % 24;
  202. u8 index = facedir * 4 + rot;
  203. param2 &= ~31;
  204. param2 |= rotate_facedir[index];
  205. } else if (cpt2 == CPT2_WALLMOUNTED ||
  206. cpt2 == CPT2_COLORED_WALLMOUNTED) {
  207. u8 wmountface = (param2 & 7);
  208. if (wmountface <= 1)
  209. return;
  210. Rotation oldrot = wallmounted_to_rot[wmountface - 2];
  211. param2 &= ~7;
  212. param2 |= rot_to_wallmounted[(oldrot - rot) & 3];
  213. }
  214. }
  215. void transformNodeBox(const MapNode &n, const NodeBox &nodebox,
  216. const NodeDefManager *nodemgr, std::vector<aabb3f> *p_boxes,
  217. u8 neighbors = 0)
  218. {
  219. std::vector<aabb3f> &boxes = *p_boxes;
  220. if (nodebox.type == NODEBOX_FIXED || nodebox.type == NODEBOX_LEVELED) {
  221. const std::vector<aabb3f> &fixed = nodebox.fixed;
  222. int facedir = n.getFaceDir(nodemgr, true);
  223. u8 axisdir = facedir>>2;
  224. facedir&=0x03;
  225. for (aabb3f box : fixed) {
  226. if (nodebox.type == NODEBOX_LEVELED)
  227. box.MaxEdge.Y = (-0.5f + n.getLevel(nodemgr) / 64.0f) * BS;
  228. switch (axisdir) {
  229. case 0:
  230. if(facedir == 1)
  231. {
  232. box.MinEdge.rotateXZBy(-90);
  233. box.MaxEdge.rotateXZBy(-90);
  234. }
  235. else if(facedir == 2)
  236. {
  237. box.MinEdge.rotateXZBy(180);
  238. box.MaxEdge.rotateXZBy(180);
  239. }
  240. else if(facedir == 3)
  241. {
  242. box.MinEdge.rotateXZBy(90);
  243. box.MaxEdge.rotateXZBy(90);
  244. }
  245. break;
  246. case 1: // z+
  247. box.MinEdge.rotateYZBy(90);
  248. box.MaxEdge.rotateYZBy(90);
  249. if(facedir == 1)
  250. {
  251. box.MinEdge.rotateXYBy(90);
  252. box.MaxEdge.rotateXYBy(90);
  253. }
  254. else if(facedir == 2)
  255. {
  256. box.MinEdge.rotateXYBy(180);
  257. box.MaxEdge.rotateXYBy(180);
  258. }
  259. else if(facedir == 3)
  260. {
  261. box.MinEdge.rotateXYBy(-90);
  262. box.MaxEdge.rotateXYBy(-90);
  263. }
  264. break;
  265. case 2: //z-
  266. box.MinEdge.rotateYZBy(-90);
  267. box.MaxEdge.rotateYZBy(-90);
  268. if(facedir == 1)
  269. {
  270. box.MinEdge.rotateXYBy(-90);
  271. box.MaxEdge.rotateXYBy(-90);
  272. }
  273. else if(facedir == 2)
  274. {
  275. box.MinEdge.rotateXYBy(180);
  276. box.MaxEdge.rotateXYBy(180);
  277. }
  278. else if(facedir == 3)
  279. {
  280. box.MinEdge.rotateXYBy(90);
  281. box.MaxEdge.rotateXYBy(90);
  282. }
  283. break;
  284. case 3: //x+
  285. box.MinEdge.rotateXYBy(-90);
  286. box.MaxEdge.rotateXYBy(-90);
  287. if(facedir == 1)
  288. {
  289. box.MinEdge.rotateYZBy(90);
  290. box.MaxEdge.rotateYZBy(90);
  291. }
  292. else if(facedir == 2)
  293. {
  294. box.MinEdge.rotateYZBy(180);
  295. box.MaxEdge.rotateYZBy(180);
  296. }
  297. else if(facedir == 3)
  298. {
  299. box.MinEdge.rotateYZBy(-90);
  300. box.MaxEdge.rotateYZBy(-90);
  301. }
  302. break;
  303. case 4: //x-
  304. box.MinEdge.rotateXYBy(90);
  305. box.MaxEdge.rotateXYBy(90);
  306. if(facedir == 1)
  307. {
  308. box.MinEdge.rotateYZBy(-90);
  309. box.MaxEdge.rotateYZBy(-90);
  310. }
  311. else if(facedir == 2)
  312. {
  313. box.MinEdge.rotateYZBy(180);
  314. box.MaxEdge.rotateYZBy(180);
  315. }
  316. else if(facedir == 3)
  317. {
  318. box.MinEdge.rotateYZBy(90);
  319. box.MaxEdge.rotateYZBy(90);
  320. }
  321. break;
  322. case 5:
  323. box.MinEdge.rotateXYBy(-180);
  324. box.MaxEdge.rotateXYBy(-180);
  325. if(facedir == 1)
  326. {
  327. box.MinEdge.rotateXZBy(90);
  328. box.MaxEdge.rotateXZBy(90);
  329. }
  330. else if(facedir == 2)
  331. {
  332. box.MinEdge.rotateXZBy(180);
  333. box.MaxEdge.rotateXZBy(180);
  334. }
  335. else if(facedir == 3)
  336. {
  337. box.MinEdge.rotateXZBy(-90);
  338. box.MaxEdge.rotateXZBy(-90);
  339. }
  340. break;
  341. default:
  342. break;
  343. }
  344. box.repair();
  345. boxes.push_back(box);
  346. }
  347. }
  348. else if(nodebox.type == NODEBOX_WALLMOUNTED)
  349. {
  350. v3s16 dir = n.getWallMountedDir(nodemgr);
  351. // top
  352. if(dir == v3s16(0,1,0))
  353. {
  354. boxes.push_back(nodebox.wall_top);
  355. }
  356. // bottom
  357. else if(dir == v3s16(0,-1,0))
  358. {
  359. boxes.push_back(nodebox.wall_bottom);
  360. }
  361. // side
  362. else
  363. {
  364. v3f vertices[2] =
  365. {
  366. nodebox.wall_side.MinEdge,
  367. nodebox.wall_side.MaxEdge
  368. };
  369. for (v3f &vertex : vertices) {
  370. if(dir == v3s16(-1,0,0))
  371. vertex.rotateXZBy(0);
  372. if(dir == v3s16(1,0,0))
  373. vertex.rotateXZBy(180);
  374. if(dir == v3s16(0,0,-1))
  375. vertex.rotateXZBy(90);
  376. if(dir == v3s16(0,0,1))
  377. vertex.rotateXZBy(-90);
  378. }
  379. aabb3f box = aabb3f(vertices[0]);
  380. box.addInternalPoint(vertices[1]);
  381. boxes.push_back(box);
  382. }
  383. }
  384. else if (nodebox.type == NODEBOX_CONNECTED)
  385. {
  386. size_t boxes_size = boxes.size();
  387. boxes_size += nodebox.fixed.size();
  388. if (neighbors & 1)
  389. boxes_size += nodebox.connect_top.size();
  390. else
  391. boxes_size += nodebox.disconnected_top.size();
  392. if (neighbors & 2)
  393. boxes_size += nodebox.connect_bottom.size();
  394. else
  395. boxes_size += nodebox.disconnected_bottom.size();
  396. if (neighbors & 4)
  397. boxes_size += nodebox.connect_front.size();
  398. else
  399. boxes_size += nodebox.disconnected_front.size();
  400. if (neighbors & 8)
  401. boxes_size += nodebox.connect_left.size();
  402. else
  403. boxes_size += nodebox.disconnected_left.size();
  404. if (neighbors & 16)
  405. boxes_size += nodebox.connect_back.size();
  406. else
  407. boxes_size += nodebox.disconnected_back.size();
  408. if (neighbors & 32)
  409. boxes_size += nodebox.connect_right.size();
  410. else
  411. boxes_size += nodebox.disconnected_right.size();
  412. if (neighbors == 0)
  413. boxes_size += nodebox.disconnected.size();
  414. if (neighbors < 4)
  415. boxes_size += nodebox.disconnected_sides.size();
  416. boxes.reserve(boxes_size);
  417. #define BOXESPUSHBACK(c) \
  418. for (std::vector<aabb3f>::const_iterator \
  419. it = (c).begin(); \
  420. it != (c).end(); ++it) \
  421. (boxes).push_back(*it);
  422. BOXESPUSHBACK(nodebox.fixed);
  423. if (neighbors & 1) {
  424. BOXESPUSHBACK(nodebox.connect_top);
  425. } else {
  426. BOXESPUSHBACK(nodebox.disconnected_top);
  427. }
  428. if (neighbors & 2) {
  429. BOXESPUSHBACK(nodebox.connect_bottom);
  430. } else {
  431. BOXESPUSHBACK(nodebox.disconnected_bottom);
  432. }
  433. if (neighbors & 4) {
  434. BOXESPUSHBACK(nodebox.connect_front);
  435. } else {
  436. BOXESPUSHBACK(nodebox.disconnected_front);
  437. }
  438. if (neighbors & 8) {
  439. BOXESPUSHBACK(nodebox.connect_left);
  440. } else {
  441. BOXESPUSHBACK(nodebox.disconnected_left);
  442. }
  443. if (neighbors & 16) {
  444. BOXESPUSHBACK(nodebox.connect_back);
  445. } else {
  446. BOXESPUSHBACK(nodebox.disconnected_back);
  447. }
  448. if (neighbors & 32) {
  449. BOXESPUSHBACK(nodebox.connect_right);
  450. } else {
  451. BOXESPUSHBACK(nodebox.disconnected_right);
  452. }
  453. if (neighbors == 0) {
  454. BOXESPUSHBACK(nodebox.disconnected);
  455. }
  456. if (neighbors < 4) {
  457. BOXESPUSHBACK(nodebox.disconnected_sides);
  458. }
  459. }
  460. else // NODEBOX_REGULAR
  461. {
  462. boxes.emplace_back(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
  463. }
  464. }
  465. static inline void getNeighborConnectingFace(
  466. const v3s16 &p, const NodeDefManager *nodedef,
  467. Map *map, MapNode n, u8 bitmask, u8 *neighbors)
  468. {
  469. MapNode n2 = map->getNodeNoEx(p);
  470. if (nodedef->nodeboxConnects(n, n2, bitmask))
  471. *neighbors |= bitmask;
  472. }
  473. u8 MapNode::getNeighbors(v3s16 p, Map *map)
  474. {
  475. const NodeDefManager *nodedef = map->getNodeDefManager();
  476. u8 neighbors = 0;
  477. const ContentFeatures &f = nodedef->get(*this);
  478. // locate possible neighboring nodes to connect to
  479. if (f.drawtype == NDT_NODEBOX && f.node_box.type == NODEBOX_CONNECTED) {
  480. v3s16 p2 = p;
  481. p2.Y++;
  482. getNeighborConnectingFace(p2, nodedef, map, *this, 1, &neighbors);
  483. p2 = p;
  484. p2.Y--;
  485. getNeighborConnectingFace(p2, nodedef, map, *this, 2, &neighbors);
  486. p2 = p;
  487. p2.Z--;
  488. getNeighborConnectingFace(p2, nodedef, map, *this, 4, &neighbors);
  489. p2 = p;
  490. p2.X--;
  491. getNeighborConnectingFace(p2, nodedef, map, *this, 8, &neighbors);
  492. p2 = p;
  493. p2.Z++;
  494. getNeighborConnectingFace(p2, nodedef, map, *this, 16, &neighbors);
  495. p2 = p;
  496. p2.X++;
  497. getNeighborConnectingFace(p2, nodedef, map, *this, 32, &neighbors);
  498. }
  499. return neighbors;
  500. }
  501. void MapNode::getNodeBoxes(const NodeDefManager *nodemgr,
  502. std::vector<aabb3f> *boxes, u8 neighbors)
  503. {
  504. const ContentFeatures &f = nodemgr->get(*this);
  505. transformNodeBox(*this, f.node_box, nodemgr, boxes, neighbors);
  506. }
  507. void MapNode::getCollisionBoxes(const NodeDefManager *nodemgr,
  508. std::vector<aabb3f> *boxes, u8 neighbors)
  509. {
  510. const ContentFeatures &f = nodemgr->get(*this);
  511. if (f.collision_box.fixed.empty())
  512. transformNodeBox(*this, f.node_box, nodemgr, boxes, neighbors);
  513. else
  514. transformNodeBox(*this, f.collision_box, nodemgr, boxes, neighbors);
  515. }
  516. void MapNode::getSelectionBoxes(const NodeDefManager *nodemgr,
  517. std::vector<aabb3f> *boxes, u8 neighbors)
  518. {
  519. const ContentFeatures &f = nodemgr->get(*this);
  520. transformNodeBox(*this, f.selection_box, nodemgr, boxes, neighbors);
  521. }
  522. u8 MapNode::getMaxLevel(const NodeDefManager *nodemgr) const
  523. {
  524. const ContentFeatures &f = nodemgr->get(*this);
  525. // todo: after update in all games leave only if (f.param_type_2 ==
  526. if( f.liquid_type == LIQUID_FLOWING || f.param_type_2 == CPT2_FLOWINGLIQUID)
  527. return LIQUID_LEVEL_MAX;
  528. if(f.leveled || f.param_type_2 == CPT2_LEVELED)
  529. return LEVELED_MAX;
  530. return 0;
  531. }
  532. u8 MapNode::getLevel(const NodeDefManager *nodemgr) const
  533. {
  534. const ContentFeatures &f = nodemgr->get(*this);
  535. // todo: after update in all games leave only if (f.param_type_2 ==
  536. if(f.liquid_type == LIQUID_SOURCE)
  537. return LIQUID_LEVEL_SOURCE;
  538. if (f.param_type_2 == CPT2_FLOWINGLIQUID)
  539. return getParam2() & LIQUID_LEVEL_MASK;
  540. if(f.liquid_type == LIQUID_FLOWING) // can remove if all param_type_2 setted
  541. return getParam2() & LIQUID_LEVEL_MASK;
  542. if(f.leveled || f.param_type_2 == CPT2_LEVELED) {
  543. u8 level = getParam2() & LEVELED_MASK;
  544. if(level)
  545. return level;
  546. if(f.leveled > LEVELED_MAX)
  547. return LEVELED_MAX;
  548. return f.leveled; //default
  549. }
  550. return 0;
  551. }
  552. u8 MapNode::setLevel(const NodeDefManager *nodemgr, s8 level)
  553. {
  554. u8 rest = 0;
  555. if (level < 1) {
  556. setContent(CONTENT_AIR);
  557. return 0;
  558. }
  559. const ContentFeatures &f = nodemgr->get(*this);
  560. if (f.param_type_2 == CPT2_FLOWINGLIQUID
  561. || f.liquid_type == LIQUID_FLOWING
  562. || f.liquid_type == LIQUID_SOURCE) {
  563. if (level >= LIQUID_LEVEL_SOURCE) {
  564. rest = level - LIQUID_LEVEL_SOURCE;
  565. setContent(nodemgr->getId(f.liquid_alternative_source));
  566. } else {
  567. setContent(nodemgr->getId(f.liquid_alternative_flowing));
  568. setParam2(level & LIQUID_LEVEL_MASK);
  569. }
  570. } else if (f.leveled || f.param_type_2 == CPT2_LEVELED) {
  571. if (level > LEVELED_MAX) {
  572. rest = level - LEVELED_MAX;
  573. level = LEVELED_MAX;
  574. }
  575. setParam2(level & LEVELED_MASK);
  576. }
  577. return rest;
  578. }
  579. u8 MapNode::addLevel(const NodeDefManager *nodemgr, s8 add)
  580. {
  581. s8 level = getLevel(nodemgr);
  582. if (add == 0) level = 1;
  583. level += add;
  584. return setLevel(nodemgr, level);
  585. }
  586. u32 MapNode::serializedLength(u8 version)
  587. {
  588. if(!ser_ver_supported(version))
  589. throw VersionMismatchException("ERROR: MapNode format not supported");
  590. if (version == 0)
  591. return 1;
  592. if (version <= 9)
  593. return 2;
  594. if (version <= 23)
  595. return 3;
  596. return 4;
  597. }
  598. void MapNode::serialize(u8 *dest, u8 version)
  599. {
  600. if(!ser_ver_supported(version))
  601. throw VersionMismatchException("ERROR: MapNode format not supported");
  602. // Can't do this anymore; we have 16-bit dynamically allocated node IDs
  603. // in memory; conversion just won't work in this direction.
  604. if(version < 24)
  605. throw SerializationError("MapNode::serialize: serialization to "
  606. "version < 24 not possible");
  607. writeU16(dest+0, param0);
  608. writeU8(dest+2, param1);
  609. writeU8(dest+3, param2);
  610. }
  611. void MapNode::deSerialize(u8 *source, u8 version)
  612. {
  613. if(!ser_ver_supported(version))
  614. throw VersionMismatchException("ERROR: MapNode format not supported");
  615. if(version <= 21)
  616. {
  617. deSerialize_pre22(source, version);
  618. return;
  619. }
  620. if(version >= 24){
  621. param0 = readU16(source+0);
  622. param1 = readU8(source+2);
  623. param2 = readU8(source+3);
  624. }else{
  625. param0 = readU8(source+0);
  626. param1 = readU8(source+1);
  627. param2 = readU8(source+2);
  628. if(param0 > 0x7F){
  629. param0 |= ((param2&0xF0)<<4);
  630. param2 &= 0x0F;
  631. }
  632. }
  633. }
  634. void MapNode::serializeBulk(std::ostream &os, int version,
  635. const MapNode *nodes, u32 nodecount,
  636. u8 content_width, u8 params_width, bool compressed)
  637. {
  638. if (!ser_ver_supported(version))
  639. throw VersionMismatchException("ERROR: MapNode format not supported");
  640. sanity_check(content_width == 2);
  641. sanity_check(params_width == 2);
  642. // Can't do this anymore; we have 16-bit dynamically allocated node IDs
  643. // in memory; conversion just won't work in this direction.
  644. if (version < 24)
  645. throw SerializationError("MapNode::serializeBulk: serialization to "
  646. "version < 24 not possible");
  647. size_t databuf_size = nodecount * (content_width + params_width);
  648. u8 *databuf = new u8[databuf_size];
  649. u32 start1 = content_width * nodecount;
  650. u32 start2 = (content_width + 1) * nodecount;
  651. // Serialize content
  652. for (u32 i = 0; i < nodecount; i++) {
  653. writeU16(&databuf[i * 2], nodes[i].param0);
  654. writeU8(&databuf[start1 + i], nodes[i].param1);
  655. writeU8(&databuf[start2 + i], nodes[i].param2);
  656. }
  657. /*
  658. Compress data to output stream
  659. */
  660. if (compressed)
  661. compressZlib(databuf, databuf_size, os);
  662. else
  663. os.write((const char*) &databuf[0], databuf_size);
  664. delete [] databuf;
  665. }
  666. // Deserialize bulk node data
  667. void MapNode::deSerializeBulk(std::istream &is, int version,
  668. MapNode *nodes, u32 nodecount,
  669. u8 content_width, u8 params_width, bool compressed)
  670. {
  671. if(!ser_ver_supported(version))
  672. throw VersionMismatchException("ERROR: MapNode format not supported");
  673. if (version < 22
  674. || (content_width != 1 && content_width != 2)
  675. || params_width != 2)
  676. FATAL_ERROR("Deserialize bulk node data error");
  677. // Uncompress or read data
  678. u32 len = nodecount * (content_width + params_width);
  679. SharedBuffer<u8> databuf(len);
  680. if(compressed)
  681. {
  682. std::ostringstream os(std::ios_base::binary);
  683. decompressZlib(is, os);
  684. std::string s = os.str();
  685. if(s.size() != len)
  686. throw SerializationError("deSerializeBulkNodes: "
  687. "decompress resulted in invalid size");
  688. memcpy(&databuf[0], s.c_str(), len);
  689. }
  690. else
  691. {
  692. is.read((char*) &databuf[0], len);
  693. if(is.eof() || is.fail())
  694. throw SerializationError("deSerializeBulkNodes: "
  695. "failed to read bulk node data");
  696. }
  697. // Deserialize content
  698. if(content_width == 1)
  699. {
  700. for(u32 i=0; i<nodecount; i++)
  701. nodes[i].param0 = readU8(&databuf[i]);
  702. }
  703. else if(content_width == 2)
  704. {
  705. for(u32 i=0; i<nodecount; i++)
  706. nodes[i].param0 = readU16(&databuf[i*2]);
  707. }
  708. // Deserialize param1
  709. u32 start1 = content_width * nodecount;
  710. for(u32 i=0; i<nodecount; i++)
  711. nodes[i].param1 = readU8(&databuf[start1 + i]);
  712. // Deserialize param2
  713. u32 start2 = (content_width + 1) * nodecount;
  714. if(content_width == 1)
  715. {
  716. for(u32 i=0; i<nodecount; i++) {
  717. nodes[i].param2 = readU8(&databuf[start2 + i]);
  718. if(nodes[i].param0 > 0x7F){
  719. nodes[i].param0 <<= 4;
  720. nodes[i].param0 |= (nodes[i].param2&0xF0)>>4;
  721. nodes[i].param2 &= 0x0F;
  722. }
  723. }
  724. }
  725. else if(content_width == 2)
  726. {
  727. for(u32 i=0; i<nodecount; i++)
  728. nodes[i].param2 = readU8(&databuf[start2 + i]);
  729. }
  730. }
  731. /*
  732. Legacy serialization
  733. */
  734. void MapNode::deSerialize_pre22(const u8 *source, u8 version)
  735. {
  736. if(version <= 1)
  737. {
  738. param0 = source[0];
  739. }
  740. else if(version <= 9)
  741. {
  742. param0 = source[0];
  743. param1 = source[1];
  744. }
  745. else
  746. {
  747. param0 = source[0];
  748. param1 = source[1];
  749. param2 = source[2];
  750. if(param0 > 0x7f){
  751. param0 <<= 4;
  752. param0 |= (param2&0xf0)>>4;
  753. param2 &= 0x0f;
  754. }
  755. }
  756. // Convert special values from old version to new
  757. if(version <= 19)
  758. {
  759. // In these versions, CONTENT_IGNORE and CONTENT_AIR
  760. // are 255 and 254
  761. // Version 19 is fucked up with sometimes the old values and sometimes not
  762. if(param0 == 255)
  763. param0 = CONTENT_IGNORE;
  764. else if(param0 == 254)
  765. param0 = CONTENT_AIR;
  766. }
  767. // Translate to our known version
  768. *this = mapnode_translate_to_internal(*this, version);
  769. }