Recipie.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. #include "Recipie.h"
  2. #include <Logging.h>
  3. #include "CraftingStorage.h"
  4. #include "Game.h"
  5. #include "Item.h"
  6. RecipieInput::RecipieInput()
  7. : ReferenceCounter(),
  8. filter(0),
  9. modifier(0),
  10. amount(0)
  11. {}
  12. RecipieInput::~RecipieInput()
  13. {
  14. if (filter) filter->release();
  15. if (modifier) modifier->release();
  16. }
  17. void RecipieInput::setFilter(ItemFilter* filter)
  18. {
  19. if (this->filter) this->filter->release();
  20. this->filter = filter;
  21. }
  22. ItemFilter* RecipieInput::zFilter() const
  23. {
  24. return filter;
  25. }
  26. void RecipieInput::setModifier(ItemModifier* modifier)
  27. {
  28. if (this->modifier) this->modifier->release();
  29. this->modifier = modifier;
  30. }
  31. ItemModifier* RecipieInput::zModifier() const
  32. {
  33. return modifier;
  34. }
  35. void RecipieInput::setAmount(int amount)
  36. {
  37. this->amount = amount;
  38. }
  39. int RecipieInput::getAmount() const
  40. {
  41. return amount;
  42. }
  43. RecipieInputFactory::RecipieInputFactory()
  44. : ObjectTypeFactory()
  45. {}
  46. RecipieInput* RecipieInputFactory::fromJson(
  47. Framework::JSON::JSONObject* zJson) const
  48. {
  49. RecipieInput* result = new RecipieInput();
  50. result->setFilter(Game::INSTANCE->zTypeRegistry()->fromJson<ItemFilter>(
  51. zJson->asObject()->zValue("filter")));
  52. result->setModifier(Game::INSTANCE->zTypeRegistry()->fromJson<ItemModifier>(
  53. zJson->asObject()->zValue("modifier")));
  54. result->setAmount(
  55. (int)zJson->asObject()->zValue("amount")->asNumber()->getNumber());
  56. return result;
  57. }
  58. Framework::JSON::JSONObject* RecipieInputFactory::toJsonObject(
  59. RecipieInput* zObject) const
  60. {
  61. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  62. result->addValue(
  63. "filter", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zFilter()));
  64. result->addValue("modifier",
  65. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModifier()));
  66. result->addValue("amount",
  67. new Framework::JSON::JSONNumber((double)zObject->getAmount()));
  68. return result;
  69. }
  70. JSONObjectValidationBuilder* RecipieInputFactory::addToValidator(
  71. JSONObjectValidationBuilder* builder) const
  72. {
  73. Framework::JSON::JSONObject* defaultModifier
  74. = new Framework::JSON::JSONObject();
  75. defaultModifier->addValue(
  76. "type", new Framework::JSON::JSONString("consume"));
  77. return builder
  78. ->withRequiredAttribute("filter",
  79. Game::INSTANCE->zTypeRegistry()->getValidator<ItemFilter>())
  80. ->withRequiredAttribute("modifier",
  81. Game::INSTANCE->zTypeRegistry()->getValidator<ItemModifier>())
  82. ->withRequiredObject("modifier")
  83. ->withRequiredString("type")
  84. ->withExactMatch("consume")
  85. ->finishString()
  86. ->withDefault(defaultModifier)
  87. ->finishObject()
  88. ->withRequiredNumber("amount")
  89. ->whichIsGreaterOrEqual(1.0)
  90. ->withDefault(1.0)
  91. ->finishNumber();
  92. }
  93. RecipieOutput::RecipieOutput()
  94. : ReferenceCounter(),
  95. itemTypeId(0),
  96. amount(0),
  97. modifier(0)
  98. {}
  99. RecipieOutput::~RecipieOutput()
  100. {
  101. modifier->release();
  102. }
  103. void RecipieOutput::setItemTypeId(int itemTypeId)
  104. {
  105. this->itemTypeId = itemTypeId;
  106. }
  107. int RecipieOutput::getItemTypeId() const
  108. {
  109. return itemTypeId;
  110. }
  111. void RecipieOutput::setAmount(int amount)
  112. {
  113. this->amount = amount;
  114. }
  115. int RecipieOutput::getAmount() const
  116. {
  117. return amount;
  118. }
  119. void RecipieOutput::setModifier(ItemModifier* modifier)
  120. {
  121. if (this->modifier) this->modifier->release();
  122. this->modifier = modifier;
  123. }
  124. ItemModifier* RecipieOutput::zModifier() const
  125. {
  126. return modifier;
  127. }
  128. Item* RecipieOutput::createItem() const
  129. {
  130. Item* result = Game::INSTANCE->zItemType(itemTypeId)->createItem();
  131. if (result)
  132. {
  133. modifier->applyOn(result);
  134. }
  135. return result;
  136. }
  137. RecipieOutputFactory::RecipieOutputFactory()
  138. : ObjectTypeFactory()
  139. {}
  140. RecipieOutput* RecipieOutputFactory::fromJson(
  141. Framework::JSON::JSONObject* zJson) const
  142. {
  143. RecipieOutput* result = new RecipieOutput();
  144. result->setItemTypeId(Game::INSTANCE->getItemTypeId(
  145. zJson->asObject()->zValue("itemType")->asString()->getString()));
  146. result->setAmount(
  147. (int)zJson->asObject()->zValue("amount")->asNumber()->getNumber());
  148. result->setModifier(Game::INSTANCE->zTypeRegistry()->fromJson<ItemModifier>(
  149. zJson->asObject()->zValue("modifier")));
  150. return result;
  151. }
  152. Framework::JSON::JSONObject* RecipieOutputFactory::toJsonObject(
  153. RecipieOutput* zObject) const
  154. {
  155. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  156. result->addValue("itemType",
  157. new Framework::JSON::JSONString(
  158. Game::INSTANCE->zItemType(zObject->getItemTypeId())->getName()));
  159. result->addValue("amount",
  160. new Framework::JSON::JSONNumber((double)zObject->getAmount()));
  161. result->addValue("modifier",
  162. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zModifier()));
  163. return result;
  164. }
  165. JSONObjectValidationBuilder* RecipieOutputFactory::addToValidator(
  166. JSONObjectValidationBuilder* builder) const
  167. {
  168. Framework::JSON::JSONObject* defaultModifier
  169. = new Framework::JSON::JSONObject();
  170. defaultModifier->addValue(
  171. "type", new Framework::JSON::JSONString("doNothing"));
  172. return builder
  173. ->withRequiredAttribute("itemType",
  174. Game::INSTANCE->zTypeRegistry()->getValidator<Framework::Text>(
  175. ItemTypeNameFactory::TYPE_ID))
  176. ->withRequiredAttribute("modifier",
  177. Game::INSTANCE->zTypeRegistry()->getValidator<ItemModifier>())
  178. ->withRequiredObject("modifier")
  179. ->withRequiredString("type")
  180. ->withExactMatch("doNothing")
  181. ->finishString()
  182. ->withDefault(defaultModifier)
  183. ->finishObject()
  184. ->withRequiredNumber("amount")
  185. ->whichIsGreaterOrEqual(1.0)
  186. ->withDefault(1.0)
  187. ->finishNumber();
  188. }
  189. Recipie::Recipie()
  190. : ReferenceCounter()
  191. {}
  192. void Recipie::addOutput(RecipieOutput* outputs)
  193. {
  194. this->outputs.add(outputs);
  195. }
  196. Framework::Array<ItemInfo> Recipie::getOutput() const
  197. {
  198. Framework::Array<ItemInfo> result;
  199. for (const RecipieOutput* output : outputs)
  200. {
  201. Item* item = output->createItem();
  202. if (item)
  203. {
  204. result.add({item->zItemType()->getId(),
  205. output->getAmount(),
  206. item->getHp(),
  207. item->getMaxHp(),
  208. item->getDurability(),
  209. item->getMaxDurability()});
  210. item->release();
  211. }
  212. }
  213. return result;
  214. }
  215. bool Recipie::createsOutput(int itemTypeId)
  216. {
  217. for (RecipieOutput* output : outputs)
  218. {
  219. if (output->getItemTypeId() == itemTypeId)
  220. {
  221. return 1;
  222. }
  223. }
  224. return 0;
  225. }
  226. void Recipie::setGroupName(Framework::Text groupName)
  227. {
  228. this->groupName = groupName;
  229. }
  230. const Framework::RCArray<RecipieOutput>& Recipie::getOutputs() const
  231. {
  232. return outputs;
  233. }
  234. Framework::Text Recipie::getGroupName() const
  235. {
  236. return groupName;
  237. }
  238. UnshapedRecipie::UnshapedRecipie()
  239. : Recipie()
  240. {}
  241. bool UnshapedRecipie::testApplicability(CraftingStorage* zStorage)
  242. {
  243. for (RecipieOutput* output : outputs)
  244. {
  245. Item* item = output->createItem();
  246. if (item)
  247. {
  248. if (!zStorage->hasFreeSpace(item, output->getAmount()))
  249. {
  250. item->release();
  251. return 0;
  252. }
  253. item->release();
  254. }
  255. }
  256. return zStorage->isAllAvailable(inputs);
  257. }
  258. void UnshapedRecipie::apply(CraftingStorage* zStorage)
  259. {
  260. zStorage->consume(inputs);
  261. for (RecipieOutput* output : outputs)
  262. {
  263. Item* item = output->createItem();
  264. if (item)
  265. {
  266. ItemStack* stack = new ItemStack(item, output->getAmount());
  267. zStorage->addCraftingResult(stack);
  268. stack->release();
  269. }
  270. }
  271. }
  272. Framework::Text UnshapedRecipie::getRecipieUIML()
  273. {
  274. Framework::Text result = "<recipie type=\"unshaped\"><ingredients>";
  275. for (RecipieInput* input : inputs)
  276. {
  277. result.append() << "<ingredient amount=\"" << input->getAmount()
  278. << "\">";
  279. if (input->zFilter())
  280. {
  281. result.append()
  282. << "<logic>" << input->zFilter()->getLogicUIML() << "</logic>";
  283. }
  284. result += "</ingredient>";
  285. // TODO: add modifiers
  286. }
  287. result += "</ingredients><outputs>";
  288. for (RecipieOutput* output : outputs)
  289. {
  290. Item* item = output->createItem();
  291. if (item)
  292. {
  293. result.append()
  294. << "<output amount=\"" << output->getAmount()
  295. << "\" itemType=\"" << item->zItemType()->getId() << "\" hp=\""
  296. << item->getHp() << "\" durability=\"" << item->getDurability()
  297. << "\" maxHp=\"" << item->getMaxHp() << "\" maxDurability=\""
  298. << item->getMaxDurability() << "\">" << item->getTooltipUIML()
  299. << "</output>";
  300. item->release();
  301. }
  302. }
  303. result += "</outputs></recipie>";
  304. return result;
  305. }
  306. void UnshapedRecipie::addInput(RecipieInput* input)
  307. {
  308. inputs.add(input);
  309. }
  310. const Framework::RCArray<RecipieInput>& UnshapedRecipie::getInputs() const
  311. {
  312. return inputs;
  313. }
  314. UnshapedRecipieFactory::UnshapedRecipieFactory()
  315. : RecipieFactory()
  316. {}
  317. UnshapedRecipie* UnshapedRecipieFactory::createValue(
  318. Framework::JSON::JSONObject* zJson) const
  319. {
  320. return new UnshapedRecipie();
  321. }
  322. UnshapedRecipie* UnshapedRecipieFactory::fromJson(
  323. Framework::JSON::JSONObject* zJson) const
  324. {
  325. UnshapedRecipie* result = RecipieFactory::fromJson(zJson);
  326. for (Framework::JSON::JSONValue* input :
  327. *zJson->zValue("inputs")->asArray())
  328. {
  329. result->addInput(
  330. Game::INSTANCE->zTypeRegistry()->fromJson<RecipieInput>(input));
  331. }
  332. return result;
  333. }
  334. Framework::JSON::JSONObject* UnshapedRecipieFactory::toJsonObject(
  335. UnshapedRecipie* zObject) const
  336. {
  337. Framework::JSON::JSONObject* result = RecipieFactory::toJsonObject(zObject);
  338. Framework::JSON::JSONArray* inputs = new Framework::JSON::JSONArray();
  339. for (RecipieInput* input : zObject->getInputs())
  340. {
  341. inputs->addValue(Game::INSTANCE->zTypeRegistry()->toJson(input));
  342. }
  343. result->addValue("inputs", inputs);
  344. return result;
  345. }
  346. JSONObjectValidationBuilder* UnshapedRecipieFactory::addToValidator(
  347. JSONObjectValidationBuilder* builder) const
  348. {
  349. return RecipieFactory::addToValidator(
  350. 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(
  529. builder->withRequiredArray("inputs")
  530. ->addAcceptedObjectInArray()
  531. ->withRequiredNumber("x")
  532. ->whichIsGreaterOrEqual(0.0)
  533. ->finishNumber()
  534. ->withRequiredNumber("y")
  535. ->whichIsGreaterOrEqual(0.0)
  536. ->finishNumber()
  537. ->withRequiredAttribute("input",
  538. Game::INSTANCE->zTypeRegistry()->getValidator<RecipieInput>())
  539. ->finishObject()
  540. ->finishArray()
  541. ->withRequiredNumber("width")
  542. ->whichIsGreaterOrEqual(1.0)
  543. ->finishNumber()
  544. ->withRequiredNumber("height")
  545. ->whichIsGreaterOrEqual(1.0)
  546. ->finishNumber());
  547. }
  548. const char* ShapedRecipieFactory::getTypeToken() const
  549. {
  550. return "shaped";
  551. }