Recipie.cpp 18 KB

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