Recipie.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. #include "Recipie.h"
  2. #include <Logging.h>
  3. #include "CraftingStorage.h"
  4. #include "Game.h"
  5. #include "Item.h"
  6. #include "UIElement.h"
  7. RecipieInput::RecipieInput()
  8. : ReferenceCounter(),
  9. filter(0),
  10. modifier(0),
  11. amount(0)
  12. {}
  13. RecipieInput::~RecipieInput()
  14. {
  15. if (filter) filter->release();
  16. if (modifier) modifier->release();
  17. }
  18. void RecipieInput::setFilter(ItemFilter* filter)
  19. {
  20. if (this->filter) this->filter->release();
  21. this->filter = filter;
  22. }
  23. ItemFilter* RecipieInput::zFilter() const
  24. {
  25. return filter;
  26. }
  27. void RecipieInput::setModifier(ItemModifier* modifier)
  28. {
  29. if (this->modifier) this->modifier->release();
  30. this->modifier = modifier;
  31. }
  32. ItemModifier* RecipieInput::zModifier() const
  33. {
  34. return modifier;
  35. }
  36. void RecipieInput::setAmount(int amount)
  37. {
  38. this->amount = amount;
  39. }
  40. int RecipieInput::getAmount() const
  41. {
  42. return amount;
  43. }
  44. RecipieInputFactory::RecipieInputFactory()
  45. : ObjectTypeFactory()
  46. {}
  47. RecipieInput* RecipieInputFactory::fromJson(
  48. Framework::JSON::JSONObject* zJson) const
  49. {
  50. RecipieInput* result = new RecipieInput();
  51. result->setFilter(Game::INSTANCE->zTypeRegistry()->fromJson<ItemFilter>(
  52. zJson->asObject()->zValue("filter")));
  53. result->setModifier(Game::INSTANCE->zTypeRegistry()->fromJson<ItemModifier>(
  54. zJson->asObject()->zValue("modifier")));
  55. result->setAmount(
  56. (int)zJson->asObject()->zValue("amount")->asNumber()->getNumber());
  57. return result;
  58. }
  59. Framework::JSON::JSONObject* RecipieInputFactory::toJsonObject(
  60. RecipieInput* zObject) const
  61. {
  62. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  63. result->addValue(
  64. "filter", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zFilter()));
  65. result->addValue("modifier",
  66. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModifier()));
  67. result->addValue("amount",
  68. new Framework::JSON::JSONNumber((double)zObject->getAmount()));
  69. return result;
  70. }
  71. JSONObjectValidationBuilder* RecipieInputFactory::addToValidator(
  72. JSONObjectValidationBuilder* builder) const
  73. {
  74. Framework::JSON::JSONObject* defaultModifier
  75. = new Framework::JSON::JSONObject();
  76. defaultModifier->addValue(
  77. "type", new Framework::JSON::JSONString("consume"));
  78. return builder
  79. ->withRequiredAttribute("filter",
  80. Game::INSTANCE->zTypeRegistry()->getValidator<ItemFilter>())
  81. ->withRequiredAttribute("modifier",
  82. Game::INSTANCE->zTypeRegistry()->getValidator<ItemModifier>())
  83. ->withRequiredObject("modifier")
  84. ->withRequiredString("type")
  85. ->withExactMatch("consume")
  86. ->finishString()
  87. ->withDefault(defaultModifier)
  88. ->finishObject()
  89. ->withRequiredNumber("amount")
  90. ->whichIsGreaterOrEqual(1.0)
  91. ->withDefault(1.0)
  92. ->finishNumber();
  93. }
  94. RecipieOutput::RecipieOutput()
  95. : ReferenceCounter(),
  96. itemTypeId(0),
  97. amount(0),
  98. modifier(0)
  99. {}
  100. RecipieOutput::~RecipieOutput()
  101. {
  102. modifier->release();
  103. }
  104. void RecipieOutput::setItemTypeId(int itemTypeId)
  105. {
  106. this->itemTypeId = itemTypeId;
  107. }
  108. int RecipieOutput::getItemTypeId() const
  109. {
  110. return itemTypeId;
  111. }
  112. void RecipieOutput::setAmount(int amount)
  113. {
  114. this->amount = amount;
  115. }
  116. int RecipieOutput::getAmount() const
  117. {
  118. return amount;
  119. }
  120. void RecipieOutput::setModifier(ItemModifier* modifier)
  121. {
  122. if (this->modifier) this->modifier->release();
  123. this->modifier = modifier;
  124. }
  125. ItemModifier* RecipieOutput::zModifier() const
  126. {
  127. return modifier;
  128. }
  129. Item* RecipieOutput::createItem() const
  130. {
  131. Item* result = Game::INSTANCE->zItemType(itemTypeId)->createItem();
  132. if (result)
  133. {
  134. modifier->applyOn(result);
  135. }
  136. return result;
  137. }
  138. RecipieOutputFactory::RecipieOutputFactory()
  139. : ObjectTypeFactory()
  140. {}
  141. RecipieOutput* RecipieOutputFactory::fromJson(
  142. Framework::JSON::JSONObject* zJson) const
  143. {
  144. RecipieOutput* result = new RecipieOutput();
  145. result->setItemTypeId(Game::INSTANCE->getItemTypeId(
  146. zJson->asObject()->zValue("itemType")->asString()->getString()));
  147. result->setAmount(
  148. (int)zJson->asObject()->zValue("amount")->asNumber()->getNumber());
  149. result->setModifier(Game::INSTANCE->zTypeRegistry()->fromJson<ItemModifier>(
  150. zJson->asObject()->zValue("modifier")));
  151. return result;
  152. }
  153. Framework::JSON::JSONObject* RecipieOutputFactory::toJsonObject(
  154. RecipieOutput* zObject) const
  155. {
  156. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  157. result->addValue("itemType",
  158. new Framework::JSON::JSONString(
  159. Game::INSTANCE->zItemType(zObject->getItemTypeId())->getName()));
  160. result->addValue("amount",
  161. new Framework::JSON::JSONNumber((double)zObject->getAmount()));
  162. result->addValue("modifier",
  163. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModifier()));
  164. return result;
  165. }
  166. JSONObjectValidationBuilder* RecipieOutputFactory::addToValidator(
  167. JSONObjectValidationBuilder* builder) const
  168. {
  169. Framework::JSON::JSONObject* defaultModifier
  170. = new Framework::JSON::JSONObject();
  171. defaultModifier->addValue(
  172. "type", new Framework::JSON::JSONString("doNothing"));
  173. return builder
  174. ->withRequiredAttribute("itemType",
  175. Game::INSTANCE->zTypeRegistry()->getValidator<Framework::Text>(
  176. ItemTypeNameFactory::TYPE_ID))
  177. ->withRequiredAttribute("modifier",
  178. Game::INSTANCE->zTypeRegistry()->getValidator<ItemModifier>())
  179. ->withRequiredObject("modifier")
  180. ->withRequiredString("type")
  181. ->withExactMatch("doNothing")
  182. ->finishString()
  183. ->withDefault(defaultModifier)
  184. ->finishObject()
  185. ->withRequiredNumber("amount")
  186. ->whichIsGreaterOrEqual(1.0)
  187. ->withDefault(1.0)
  188. ->finishNumber();
  189. }
  190. Recipie::Recipie()
  191. : ReferenceCounter()
  192. {}
  193. void Recipie::addOutput(RecipieOutput* outputs)
  194. {
  195. this->outputs.add(outputs);
  196. }
  197. Framework::Array<ItemInfo> Recipie::getOutput() const
  198. {
  199. Framework::Array<ItemInfo> result;
  200. for (const RecipieOutput* output : outputs)
  201. {
  202. Item* item = output->createItem();
  203. if (item)
  204. {
  205. result.add({item->zItemType()->getId(),
  206. output->getAmount(),
  207. item->getHp(),
  208. item->getMaxHp(),
  209. item->getDurability(),
  210. item->getMaxDurability()});
  211. item->release();
  212. }
  213. }
  214. return result;
  215. }
  216. bool Recipie::createsOutput(int itemTypeId)
  217. {
  218. for (RecipieOutput* output : outputs)
  219. {
  220. if (output->getItemTypeId() == itemTypeId)
  221. {
  222. return 1;
  223. }
  224. }
  225. return 0;
  226. }
  227. void Recipie::setGroupName(Framework::Text groupName)
  228. {
  229. this->groupName = groupName;
  230. }
  231. const Framework::RCArray<RecipieOutput>& Recipie::getOutputs() const
  232. {
  233. return outputs;
  234. }
  235. Framework::Text Recipie::getGroupName() const
  236. {
  237. return groupName;
  238. }
  239. UnshapedRecipie::UnshapedRecipie()
  240. : Recipie()
  241. {}
  242. bool UnshapedRecipie::testApplicability(CraftingStorage* zStorage)
  243. {
  244. for (RecipieOutput* output : outputs)
  245. {
  246. Item* item = output->createItem();
  247. if (item)
  248. {
  249. if (!zStorage->hasFreeSpace(item, output->getAmount()))
  250. {
  251. item->release();
  252. return 0;
  253. }
  254. item->release();
  255. }
  256. }
  257. return zStorage->isAllAvailable(inputs);
  258. }
  259. void UnshapedRecipie::apply(CraftingStorage* zStorage)
  260. {
  261. zStorage->consume(inputs);
  262. for (RecipieOutput* output : outputs)
  263. {
  264. Item* item = output->createItem();
  265. if (item)
  266. {
  267. ItemStack* stack = new ItemStack(item, output->getAmount());
  268. zStorage->addCraftingResult(stack);
  269. stack->release();
  270. }
  271. }
  272. }
  273. Framework::Text UnshapedRecipie::getRecipieUIML()
  274. {
  275. Framework::Text result = "<recipie type=\"unshaped\"><ingredients>";
  276. for (RecipieInput* input : inputs)
  277. {
  278. result.append() << "<ingredient amount=\"" << input->getAmount()
  279. << "\">";
  280. if (input->zFilter())
  281. {
  282. result.append()
  283. << "<logic>" << input->zFilter()->getLogicUIML() << "</logic>";
  284. }
  285. result += "</ingredient>";
  286. // TODO: add modifiers
  287. }
  288. result += "</ingredients><outputs>";
  289. for (RecipieOutput* output : outputs)
  290. {
  291. Item* item = output->createItem();
  292. if (item)
  293. {
  294. result.append()
  295. << "<output amount=\"" << output->getAmount()
  296. << "\" itemType=\"" << item->zItemType()->getId() << "\" hp=\""
  297. << item->getHp() << "\" durability=\"" << item->getDurability()
  298. << "\" maxHp=\"" << item->getMaxHp() << "\" maxDurability=\""
  299. << item->getMaxDurability() << "\">" << item->getTooltipUIML()
  300. << "</output>";
  301. item->release();
  302. }
  303. }
  304. result += "</outputs></recipie>";
  305. return result;
  306. }
  307. void UnshapedRecipie::addInput(RecipieInput* input)
  308. {
  309. inputs.add(input);
  310. }
  311. const Framework::RCArray<RecipieInput>& UnshapedRecipie::getInputs() const
  312. {
  313. return inputs;
  314. }
  315. UnshapedRecipieFactory::UnshapedRecipieFactory()
  316. : RecipieFactory()
  317. {}
  318. UnshapedRecipie* UnshapedRecipieFactory::createValue(
  319. Framework::JSON::JSONObject* zJson) const
  320. {
  321. return new UnshapedRecipie();
  322. }
  323. UnshapedRecipie* UnshapedRecipieFactory::fromJson(
  324. Framework::JSON::JSONObject* zJson) const
  325. {
  326. UnshapedRecipie* result = RecipieFactory::fromJson(zJson);
  327. for (Framework::JSON::JSONValue* input :
  328. *zJson->zValue("inputs")->asArray())
  329. {
  330. result->addInput(
  331. Game::INSTANCE->zTypeRegistry()->fromJson<RecipieInput>(input));
  332. }
  333. return result;
  334. }
  335. Framework::JSON::JSONObject* UnshapedRecipieFactory::toJsonObject(
  336. UnshapedRecipie* zObject) const
  337. {
  338. Framework::JSON::JSONObject* result = RecipieFactory::toJsonObject(zObject);
  339. Framework::JSON::JSONArray* inputs = new Framework::JSON::JSONArray();
  340. for (RecipieInput* input : zObject->getInputs())
  341. {
  342. inputs->addValue(Game::INSTANCE->zTypeRegistry()->toJson(input));
  343. }
  344. result->addValue("inputs", inputs);
  345. return result;
  346. }
  347. JSONObjectValidationBuilder* UnshapedRecipieFactory::addToValidator(
  348. JSONObjectValidationBuilder* builder) const
  349. {
  350. return RecipieFactory::addToValidator(builder->withRequiredArray("inputs")
  351. ->addAcceptedTypeInArray(
  352. Game::INSTANCE->zTypeRegistry()->getValidator<RecipieInput>())
  353. ->finishArray());
  354. }
  355. const char* UnshapedRecipieFactory::getTypeToken() const
  356. {
  357. return "unshaped";
  358. }
  359. ShapedRecipie::ShapedRecipie()
  360. : Recipie(),
  361. width(0),
  362. height(0)
  363. {}
  364. bool ShapedRecipie::testApplicability(CraftingStorage* zStorage)
  365. {
  366. ShapedCraftingStorage* zShapedStorage
  367. = dynamic_cast<ShapedCraftingStorage*>(zStorage);
  368. if (!zShapedStorage) return 0;
  369. for (RecipieOutput* output : outputs)
  370. {
  371. Item* item = output->createItem();
  372. if (item)
  373. {
  374. if (!zShapedStorage->hasFreeSpace(item, output->getAmount()))
  375. {
  376. item->release();
  377. return 0;
  378. }
  379. item->release();
  380. }
  381. }
  382. return zShapedStorage->isAllAvailable(inputs, width, height);
  383. }
  384. void ShapedRecipie::apply(CraftingStorage* zStorage)
  385. {
  386. ShapedCraftingStorage* zShapedStorage
  387. = dynamic_cast<ShapedCraftingStorage*>(zStorage);
  388. zShapedStorage->consume(inputs, width, height);
  389. for (RecipieOutput* output : outputs)
  390. {
  391. Item* item = output->createItem();
  392. if (item)
  393. {
  394. ItemStack* stack = new ItemStack(item, output->getAmount());
  395. zStorage->addCraftingResult(stack);
  396. stack->release();
  397. }
  398. }
  399. }
  400. Framework::Text ShapedRecipie::getRecipieUIML()
  401. {
  402. Framework::Text result = "<recipie type=\"shaped\" width=\"";
  403. result.append() << width << "\" height=\"" << height << "\"><ingredients>";
  404. for (RecipieInput* input : inputs)
  405. {
  406. result.append() << "<ingredient amount=\"" << input->getAmount()
  407. << "\">";
  408. if (input->zFilter())
  409. {
  410. result.append()
  411. << "<logic>" << input->zFilter()->getLogicUIML() << "</logic>";
  412. }
  413. result += "</ingredient>";
  414. // TODO: add modifiers
  415. }
  416. result += "</ingredients><outputs>";
  417. for (RecipieOutput* output : outputs)
  418. {
  419. Item* item = output->createItem();
  420. if (item)
  421. {
  422. result.append()
  423. << "<output amount=\"" << output->getAmount()
  424. << "\" itemType=\"" << item->zItemType()->getId() << "\" hp=\""
  425. << item->getHp() << "\" durability=\"" << item->getDurability()
  426. << "\" maxHp=\"" << item->getMaxHp() << "\" maxDurability=\""
  427. << item->getMaxDurability() << "\">" << item->getTooltipUIML()
  428. << "</output>";
  429. item->release();
  430. }
  431. }
  432. result += "</outputs></recipie>";
  433. return result;
  434. }
  435. void ShapedRecipie::setWidth(int width)
  436. {
  437. this->width = width;
  438. }
  439. int ShapedRecipie::getWidth() const
  440. {
  441. return width;
  442. }
  443. void ShapedRecipie::setHeight(int height)
  444. {
  445. this->height = height;
  446. }
  447. int ShapedRecipie::getHeight() const
  448. {
  449. return height;
  450. }
  451. void ShapedRecipie::addInput(RecipieInput* input)
  452. {
  453. inputs.add(input);
  454. }
  455. void ShapedRecipie::setInput(int index, RecipieInput* input)
  456. {
  457. inputs.set(input, index);
  458. }
  459. const Framework::RCArray<RecipieInput>& ShapedRecipie::getInputs() const
  460. {
  461. return inputs;
  462. }
  463. ShapedRecipieFactory::ShapedRecipieFactory()
  464. : RecipieFactory()
  465. {}
  466. ShapedRecipie* ShapedRecipieFactory::createValue(
  467. Framework::JSON::JSONObject* zJson) const
  468. {
  469. return new ShapedRecipie();
  470. }
  471. ShapedRecipie* ShapedRecipieFactory::fromJson(
  472. Framework::JSON::JSONObject* zJson) const
  473. {
  474. ShapedRecipie* result = RecipieFactory::fromJson(zJson);
  475. int width = (int)zJson->zValue("width")->asNumber()->getNumber();
  476. int height = (int)zJson->zValue("height")->asNumber()->getNumber();
  477. for (int i = 0; i < width * height; i++)
  478. {
  479. result->addInput(new RecipieInput());
  480. }
  481. for (Framework::JSON::JSONValue* input :
  482. *zJson->zValue("inputs")->asArray())
  483. {
  484. int x = (int)input->asObject()->zValue("x")->asNumber()->getNumber();
  485. int y = (int)input->asObject()->zValue("y")->asNumber()->getNumber();
  486. if (x >= width || y >= height)
  487. {
  488. Framework::Logging::warning()
  489. << "Invalid input position in shaped recipie with width="
  490. << width << ", height=" << height << ", x=" << x << ", y=" << y
  491. << " input " << input->toString() << " will be ignored.";
  492. continue;
  493. }
  494. result->setInput(y * width + x,
  495. Game::INSTANCE->zTypeRegistry()->fromJson<RecipieInput>(
  496. input->asObject()->zValue("input")));
  497. }
  498. result->setWidth((int)zJson->zValue("width")->asNumber()->getNumber());
  499. result->setHeight((int)zJson->zValue("height")->asNumber()->getNumber());
  500. return result;
  501. }
  502. Framework::JSON::JSONObject* ShapedRecipieFactory::toJsonObject(
  503. ShapedRecipie* zObject) const
  504. {
  505. Framework::JSON::JSONObject* result = RecipieFactory::toJsonObject(zObject);
  506. result->addValue(
  507. "width", new Framework::JSON::JSONNumber(zObject->getWidth()));
  508. result->addValue(
  509. "height", new Framework::JSON::JSONNumber(zObject->getHeight()));
  510. Framework::JSON::JSONArray* inputs = new Framework::JSON::JSONArray();
  511. for (int i = 0; i < zObject->getWidth() * zObject->getHeight(); i++)
  512. {
  513. Framework::JSON::JSONObject* input = new Framework::JSON::JSONObject();
  514. input->addValue(
  515. "x", new Framework::JSON::JSONNumber(i % zObject->getHeight()));
  516. input->addValue(
  517. "y", new Framework::JSON::JSONNumber(i / zObject->getHeight()));
  518. input->addValue("input",
  519. Game::INSTANCE->zTypeRegistry()->toJson(zObject->getInputs().z(i)));
  520. inputs->addValue(input);
  521. }
  522. result->addValue("inputs", inputs);
  523. return result;
  524. }
  525. JSONObjectValidationBuilder* ShapedRecipieFactory::addToValidator(
  526. JSONObjectValidationBuilder* builder) const
  527. {
  528. return RecipieFactory::addToValidator(builder->withRequiredArray("inputs")
  529. ->addAcceptedObjectInArray()
  530. ->withRequiredNumber("x")
  531. ->whichIsGreaterOrEqual(0.0)
  532. ->finishNumber()
  533. ->withRequiredNumber("y")
  534. ->whichIsGreaterOrEqual(0.0)
  535. ->finishNumber()
  536. ->withRequiredAttribute("input",
  537. Game::INSTANCE->zTypeRegistry()->getValidator<RecipieInput>())
  538. ->finishObject()
  539. ->finishArray()
  540. ->withRequiredNumber("width")
  541. ->whichIsGreaterOrEqual(1.0)
  542. ->finishNumber()
  543. ->withRequiredNumber("height")
  544. ->whichIsGreaterOrEqual(1.0)
  545. ->finishNumber());
  546. }
  547. const char* ShapedRecipieFactory::getTypeToken() const
  548. {
  549. return "shaped";
  550. }