VoxeLands.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

content_nodemeta_blocks.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /************************************************************************
  2. * Minetest-c55
  3. * Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. *
  5. * content_nodemeta.cpp
  6. * voxelands - 3d voxel world sandbox game
  7. * Copyright (C) Lisa 'darkrose' Milne 2013-2017 <lisa@ltmnet.com>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. * See the GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. *
  22. * License updated from GPLv2 or later to GPLv3 or later by Lisa Milne
  23. * for Voxelands.
  24. ************************************************************************/
  25. #include "common.h"
  26. #include "content_nodemeta.h"
  27. #include "inventory.h"
  28. #include "content_mapnode.h"
  29. #include "environment.h"
  30. /*
  31. ClockNodeMetadata
  32. */
  33. // Prototype
  34. ClockNodeMetadata proto_ClockNodeMetadata;
  35. ClockNodeMetadata::ClockNodeMetadata():
  36. m_time(0)
  37. {
  38. NodeMetadata::registerType(typeId(), create);
  39. }
  40. u16 ClockNodeMetadata::typeId() const
  41. {
  42. return CONTENT_CLOCK;
  43. }
  44. NodeMetadata* ClockNodeMetadata::create(std::istream &is)
  45. {
  46. ClockNodeMetadata *d = new ClockNodeMetadata();
  47. int temp;
  48. is>>temp;
  49. d->m_time = temp;
  50. return d;
  51. }
  52. NodeMetadata* ClockNodeMetadata::clone()
  53. {
  54. ClockNodeMetadata *d = new ClockNodeMetadata();
  55. d->m_time = m_time;
  56. return d;
  57. }
  58. void ClockNodeMetadata::serializeBody(std::ostream &os)
  59. {
  60. os<<itos(m_time) << " ";
  61. }
  62. std::vector<NodeBox> ClockNodeMetadata::getNodeBoxes(MapNode &n) {
  63. std::vector<NodeBox> boxes;
  64. boxes.clear();
  65. u16 h = m_time/100;
  66. u16 m = (u16)((float)(m_time%100)/1.6667);
  67. u16 v[4];
  68. v[0] = h/10;
  69. v[1] = h%10;
  70. v[2] = m/10;
  71. v[3] = m%10;
  72. f32 x[4] = {-0.180,0.0225,0.2925,0.5};
  73. u8 b[10] = {0xFC,0x0C,0xB6,0x9E,0x4E,0xDA,0xFA,0x8C,0xFE,0xDE};
  74. float z1 = -0.125;
  75. float z2 = -0.0625;
  76. for (int i=0; i<4; i++) {
  77. // clock numbers are built from 7 segments
  78. // top
  79. if ((b[v[i]]&0x80))
  80. boxes.push_back(NodeBox((-0.25+x[i])*BS,0.0625*BS,z1*BS,(-0.0625+x[i])*BS,0.125*BS,z2*BS));
  81. // top right
  82. if ((b[v[i]]&0x04))
  83. boxes.push_back(NodeBox((-0.125+x[i])*BS,-0.125*BS,z1*BS,(-0.0625+x[i])*BS,0.125*BS,z2*BS));
  84. // bottom right
  85. if ((b[v[i]]&0x08))
  86. boxes.push_back(NodeBox((-0.125+x[i])*BS,-0.3125*BS,z1*BS,(-0.0625+x[i])*BS,-0.0625*BS,z2*BS));
  87. // bottom
  88. if ((b[v[i]]&0x10))
  89. boxes.push_back(NodeBox((-0.25+x[i])*BS,-0.3125*BS,z1*BS,(-0.0625+x[i])*BS,-0.25*BS,z2*BS));
  90. // bottom left
  91. if ((b[v[i]]&0x20))
  92. boxes.push_back(NodeBox((-0.25+x[i])*BS,-0.3125*BS,z1*BS,(-0.1875+x[i])*BS,-0.0625*BS,z2*BS));
  93. // top left
  94. if ((b[v[i]]&0x40))
  95. boxes.push_back(NodeBox((-0.25+x[i])*BS,-0.125*BS,z1*BS,(-0.1875+x[i])*BS,0.125*BS,z2*BS));
  96. // middle
  97. if ((b[v[i]]&0x02))
  98. boxes.push_back(NodeBox((-0.25+x[i])*BS,-0.125*BS,z1*BS,(-0.0625+x[i])*BS,-0.0625*BS,z2*BS));
  99. }
  100. return boxes;
  101. }
  102. bool ClockNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
  103. {
  104. u32 t = env->getTimeOfDay();
  105. t /= 10;
  106. if (t == m_time)
  107. return false;
  108. m_time = t;
  109. return true;
  110. }
  111. /*
  112. CauldronNodeMetadata
  113. */
  114. // Prototype
  115. CauldronNodeMetadata proto_CauldronNodeMetadata;
  116. CauldronNodeMetadata::CauldronNodeMetadata():
  117. m_water_level(0),
  118. m_water_heated(false),
  119. m_water_hot(false),
  120. m_fuel_time(0.0),
  121. m_src_time(0.0),
  122. m_cool_time(0.0)
  123. {
  124. NodeMetadata::registerType(typeId(), create);
  125. m_inventory = new Inventory();
  126. m_inventory->addList("fuel", 1);
  127. }
  128. CauldronNodeMetadata::~CauldronNodeMetadata()
  129. {
  130. delete m_inventory;
  131. }
  132. u16 CauldronNodeMetadata::typeId() const
  133. {
  134. return CONTENT_CAULDRON;
  135. }
  136. NodeMetadata* CauldronNodeMetadata::clone()
  137. {
  138. CauldronNodeMetadata *d = new CauldronNodeMetadata();
  139. d->m_fuel_time = m_fuel_time;
  140. d->m_src_time = m_src_time;
  141. d->m_water_level = m_water_level;
  142. d->m_water_heated = m_water_heated;
  143. d->m_water_hot = m_water_hot;
  144. *d->m_inventory = *m_inventory;
  145. return d;
  146. }
  147. NodeMetadata* CauldronNodeMetadata::create(std::istream &is)
  148. {
  149. CauldronNodeMetadata *d = new CauldronNodeMetadata();
  150. d->m_inventory->deSerialize(is);
  151. int temp;
  152. is>>temp;
  153. d->m_fuel_time = (float)temp/10;
  154. is>>temp;
  155. d->m_src_time = (float)temp/10;
  156. is>>temp;
  157. d->m_cool_time = (float)temp/10;
  158. is>>temp;
  159. d->m_water_level = temp;
  160. is>>temp;
  161. d->m_water_heated = !!temp;
  162. is>>temp;
  163. d->m_water_hot = !!temp;
  164. return d;
  165. }
  166. void CauldronNodeMetadata::serializeBody(std::ostream &os)
  167. {
  168. m_inventory->serialize(os);
  169. os<<itos(m_fuel_time*10)<<" ";
  170. os<<itos(m_src_time*10)<<" ";
  171. os<<itos(m_cool_time*10)<<" ";
  172. os<<itos(m_water_level)<<" ";
  173. os<<itos(m_water_heated ? 1 : 0)<<" ";
  174. os<<itos(m_water_hot ? 1 : 0)<<" ";
  175. }
  176. std::wstring CauldronNodeMetadata::infoText()
  177. {
  178. if (m_fuel_time)
  179. return narrow_to_wide(gettext("Cauldron is active"));
  180. if (m_water_level) {
  181. if (m_water_hot)
  182. return narrow_to_wide(gettext("Cauldron is hot"));
  183. if (m_water_heated)
  184. return narrow_to_wide(gettext("Cauldron is cool"));
  185. }else{
  186. return narrow_to_wide(gettext("Cauldron is empty"));
  187. }
  188. InventoryList *list = m_inventory->getList("fuel");
  189. if (list && list->getUsedSlots() > 0)
  190. return narrow_to_wide(gettext("Cauldron is inactive"));
  191. return narrow_to_wide(gettext("Cauldron is out of fuel"));
  192. }
  193. bool CauldronNodeMetadata::nodeRemovalDisabled()
  194. {
  195. /*
  196. Disable removal if not empty
  197. */
  198. InventoryList *list = m_inventory->getList("fuel");
  199. if (list && list->getUsedSlots() > 0)
  200. return true;
  201. if (m_water_level)
  202. return true;
  203. return false;
  204. }
  205. void CauldronNodeMetadata::inventoryModified()
  206. {
  207. vlprintf(CN_INFO,"Cauldron inventory modification callback");
  208. }
  209. bool CauldronNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
  210. {
  211. if (m_fuel_time > 0.0) {
  212. if (!m_water_heated)
  213. m_src_time += dtime;
  214. m_fuel_time -= dtime;
  215. }
  216. InventoryList *list = m_inventory->getList("fuel");
  217. bool should_heat = false;
  218. if (m_water_level) {
  219. if (m_water_hot) {
  220. m_cool_time -= dtime;
  221. if (m_cool_time < 20.0)
  222. m_water_hot = false;
  223. }else if (!m_water_heated) {
  224. m_cool_time = 120.0;
  225. if (m_src_time < 2.0) {
  226. should_heat = true;
  227. }else{
  228. m_water_hot = true;
  229. m_water_heated = true;
  230. m_src_time = 0.0;
  231. }
  232. }else if (list && list->getUsedSlots() > 0) {
  233. m_cool_time -= dtime;
  234. if (m_cool_time < 0.0)
  235. m_water_heated = false;
  236. }
  237. }else{
  238. m_water_hot = false;
  239. m_water_heated = false;
  240. }
  241. if (should_heat && m_fuel_time <= 0.0) {
  242. InventoryList *list = m_inventory->getList("fuel");
  243. InventoryItem *fitem;
  244. if (list && list->getUsedSlots() > 0 && (fitem = list->getItem(0)) != NULL && fitem->isFuel()) {
  245. if ((fitem->getContent()&CONTENT_CRAFTITEM_MASK) == CONTENT_CRAFTITEM_MASK) {
  246. m_fuel_time = ((CraftItem*)fitem)->getFuelTime();
  247. }else if ((fitem->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
  248. m_fuel_time = ((ToolItem*)fitem)->getFuelTime();
  249. }else{
  250. m_fuel_time = ((MaterialItem*)fitem)->getFuelTime();
  251. }
  252. content_t c = fitem->getContent();
  253. list->decrementMaterials(1);
  254. if (c == CONTENT_TOOLITEM_IRON_BUCKET_LAVA)
  255. list->addItem(0,new ToolItem(CONTENT_TOOLITEM_IRON_BUCKET,0,0));
  256. return true;
  257. }
  258. }
  259. return false;
  260. }
  261. std::string CauldronNodeMetadata::getDrawSpecString(Player *player)
  262. {
  263. std::string spec("size[8,7]");
  264. spec += "label[1,0.5;";
  265. spec += gettext("Add fuel, then punch to add or remove water");;
  266. spec += "]";
  267. spec += "label[3.5,1.5;";
  268. spec += gettext("Fuel");;
  269. spec += "]";
  270. spec += "list[current_name;fuel;4,1;1,1;]";
  271. spec += "list[current_player;main;0,3;8,4;]";
  272. return spec;
  273. }
  274. std::vector<NodeBox> CauldronNodeMetadata::getNodeBoxes(MapNode &n) {
  275. std::vector<NodeBox> boxes;
  276. boxes.clear();
  277. if (m_fuel_time)
  278. boxes.push_back(NodeBox(-0.125*BS,-0.5*BS,-0.125*BS,0.125*BS,-0.25*BS,0.125*BS));
  279. if (m_water_level) {
  280. switch (m_water_level) {
  281. case 1:
  282. boxes.push_back(NodeBox(-0.375*BS,-0.0625*BS,-0.375*BS,0.375*BS,0.0625*BS,0.375*BS));
  283. break;
  284. case 2:
  285. boxes.push_back(NodeBox(-0.375*BS,-0.0625*BS,-0.375*BS,0.375*BS,0.1875*BS,0.375*BS));
  286. break;
  287. case 3:
  288. boxes.push_back(NodeBox(-0.375*BS,-0.0625*BS,-0.375*BS,0.375*BS,0.3125*BS,0.375*BS));
  289. break;
  290. default:
  291. boxes.push_back(NodeBox(-0.375*BS,-0.0625*BS,-0.375*BS,0.375*BS,0.4375*BS,0.375*BS));
  292. break;
  293. }
  294. }
  295. return transformNodeBox(n,boxes);
  296. }
  297. /*
  298. BushNodeMetadata
  299. */
  300. // Prototype
  301. BushNodeMetadata proto_BushNodeMetadata;
  302. BushNodeMetadata::BushNodeMetadata()
  303. {
  304. NodeMetadata::registerType(typeId(), create);
  305. m_inventory = new Inventory();
  306. m_inventory->addList("main", 1);
  307. m_days_since_growth = -1;
  308. }
  309. BushNodeMetadata::~BushNodeMetadata()
  310. {
  311. }
  312. u16 BushNodeMetadata::typeId() const
  313. {
  314. return CONTENT_BUSH_RASPBERRY;
  315. }
  316. NodeMetadata* BushNodeMetadata::clone()
  317. {
  318. BushNodeMetadata *d = new BushNodeMetadata();
  319. *d->m_inventory = *m_inventory;
  320. d->m_days_since_growth = m_days_since_growth;
  321. return d;
  322. }
  323. NodeMetadata* BushNodeMetadata::create(std::istream &is)
  324. {
  325. BushNodeMetadata *d = new BushNodeMetadata();
  326. d->m_inventory->deSerialize(is);
  327. return d;
  328. }
  329. void BushNodeMetadata::serializeBody(std::ostream &os)
  330. {
  331. m_inventory->serialize(os);
  332. }
  333. void BushNodeMetadata::inventoryModified()
  334. {
  335. vlprintf(CN_INFO,"Bush inventory modification callback");
  336. }
  337. bool BushNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
  338. {
  339. if (berryCount() > 8)
  340. return false;
  341. if (env->getSeason() != ENV_SEASON_SPRING)
  342. return false;
  343. u32 day = env->getTime();
  344. if (m_days_since_growth < 0) {
  345. m_days_since_growth = day;
  346. return true;
  347. }
  348. if (day-m_days_since_growth < 10) {
  349. return true;
  350. }
  351. InventoryList *list = m_inventory->getList("main");
  352. if (!list)
  353. return true;
  354. InventoryItem *item;
  355. MapNode n = env->getMap().getNodeNoEx(pos);
  356. content_t berry = content_features(n.getContent()).special_alternate_node;
  357. if (berry == CONTENT_IGNORE)
  358. return false;
  359. item = new CraftItem(berry,2,0);
  360. item = list->addItem(item);
  361. if (item)
  362. delete item;
  363. m_days_since_growth = day;
  364. return true;
  365. }
  366. u16 BushNodeMetadata::berryCount()
  367. {
  368. InventoryList *list = m_inventory->getList("main");
  369. if (!list)
  370. return 0;
  371. InventoryItem *item = list->getItem(0);
  372. if (!item)
  373. return 0;
  374. return item->getCount();
  375. }