Recipie.cpp 18 KB

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