craftdef.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include <string>
  18. #include <iostream>
  19. #include <vector>
  20. #include <utility>
  21. #include "gamedef.h"
  22. #include "inventory.h"
  23. /*
  24. Crafting methods.
  25. The crafting method depends on the inventory list
  26. that the crafting input comes from.
  27. */
  28. enum CraftMethod
  29. {
  30. // Crafting grid
  31. CRAFT_METHOD_NORMAL,
  32. // Cooking something in a furnace
  33. CRAFT_METHOD_COOKING,
  34. // Using something as fuel for a furnace
  35. CRAFT_METHOD_FUEL,
  36. };
  37. /*
  38. The type a hash can be. The earlier a type is mentioned in this enum,
  39. the earlier it is tried at crafting, and the less likely is a collision.
  40. Changing order causes changes in behavior, so know what you do.
  41. */
  42. enum CraftHashType
  43. {
  44. // Hashes the normalized names of the recipe's elements.
  45. // Only recipes without group usage can be found here,
  46. // because groups can't be guessed efficiently.
  47. CRAFT_HASH_TYPE_ITEM_NAMES,
  48. // Counts the non-empty slots.
  49. CRAFT_HASH_TYPE_COUNT,
  50. // This layer both spares an extra variable, and helps to retain (albeit rarely used) functionality. Maps to 0.
  51. // Before hashes are "initialized", all hashes reside here, after initialisation, none are.
  52. CRAFT_HASH_TYPE_UNHASHED
  53. };
  54. const int craft_hash_type_max = (int) CRAFT_HASH_TYPE_UNHASHED;
  55. /*
  56. Input: The contents of the crafting slots, arranged in matrix form
  57. */
  58. struct CraftInput
  59. {
  60. CraftMethod method = CRAFT_METHOD_NORMAL;
  61. unsigned int width = 0;
  62. std::vector<ItemStack> items;
  63. CraftInput() = default;
  64. CraftInput(CraftMethod method_, unsigned int width_,
  65. const std::vector<ItemStack> &items_):
  66. method(method_), width(width_), items(items_)
  67. {}
  68. // Returns true if all items are empty.
  69. bool empty() const;
  70. std::string dump() const;
  71. };
  72. /*
  73. Output: Result of crafting operation
  74. */
  75. struct CraftOutput
  76. {
  77. // Used for normal crafting and cooking, itemstring
  78. std::string item = "";
  79. // Used for cooking (cook time) and fuel (burn time), seconds
  80. float time = 0.0f;
  81. CraftOutput() = default;
  82. CraftOutput(const std::string &item_, float time_):
  83. item(item_), time(time_)
  84. {}
  85. std::string dump() const;
  86. };
  87. /*
  88. A list of replacements. A replacement indicates that a specific
  89. input item should not be deleted (when crafting) but replaced with
  90. a different item. Each replacements is a pair (itemstring to remove,
  91. itemstring to replace with)
  92. Example: If ("bucket:bucket_water", "bucket:bucket_empty") is a
  93. replacement pair, the crafting input slot that contained a water
  94. bucket will contain an empty bucket after crafting.
  95. */
  96. struct CraftReplacements
  97. {
  98. // List of replacements
  99. std::vector<std::pair<std::string, std::string> > pairs;
  100. CraftReplacements() = default;
  101. CraftReplacements(const std::vector<std::pair<std::string, std::string> > &pairs_):
  102. pairs(pairs_)
  103. {}
  104. std::string dump() const;
  105. };
  106. /*
  107. Crafting definition base class
  108. */
  109. class CraftDefinition
  110. {
  111. public:
  112. /*
  113. Craft recipe priorities, from low to high
  114. Recipes are searched from latest to first.
  115. If a recipe with higher priority than a previous found one is
  116. encountered, it is selected instead.
  117. */
  118. enum RecipePriority
  119. {
  120. PRIORITY_NO_RECIPE,
  121. PRIORITY_TOOLREPAIR,
  122. PRIORITY_SHAPELESS_AND_GROUPS,
  123. PRIORITY_SHAPELESS,
  124. PRIORITY_SHAPED_AND_GROUPS,
  125. PRIORITY_SHAPED,
  126. };
  127. CraftDefinition() = default;
  128. virtual ~CraftDefinition() = default;
  129. // Returns type of crafting definition
  130. virtual std::string getName() const=0;
  131. // Checks whether the recipe is applicable
  132. virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
  133. RecipePriority getPriority() const
  134. {
  135. return priority;
  136. }
  137. // Returns the output structure, meaning depends on crafting method
  138. // The implementation can assume that check(input) returns true
  139. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
  140. // the inverse of the above
  141. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
  142. // Decreases count of every input item
  143. virtual void decrementInput(CraftInput &input,
  144. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const=0;
  145. CraftHashType getHashType() const
  146. {
  147. return hash_type;
  148. }
  149. virtual u64 getHash(CraftHashType type) const = 0;
  150. // to be called after all mods are loaded, so that we catch all aliases
  151. virtual void initHash(IGameDef *gamedef) = 0;
  152. virtual std::string dump() const=0;
  153. protected:
  154. CraftHashType hash_type;
  155. RecipePriority priority;
  156. };
  157. /*
  158. A plain-jane (shaped) crafting definition
  159. Supported crafting method: CRAFT_METHOD_NORMAL.
  160. Requires the input items to be arranged exactly like in the recipe.
  161. */
  162. class CraftDefinitionShaped: public CraftDefinition
  163. {
  164. public:
  165. CraftDefinitionShaped() = delete;
  166. CraftDefinitionShaped(
  167. const std::string &output_,
  168. unsigned int width_,
  169. const std::vector<std::string> &recipe_,
  170. const CraftReplacements &replacements_);
  171. virtual ~CraftDefinitionShaped() = default;
  172. virtual std::string getName() const;
  173. virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
  174. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
  175. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
  176. virtual void decrementInput(CraftInput &input,
  177. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
  178. virtual u64 getHash(CraftHashType type) const;
  179. virtual void initHash(IGameDef *gamedef);
  180. virtual std::string dump() const;
  181. private:
  182. // Output itemstring
  183. std::string output = "";
  184. // Width of recipe
  185. unsigned int width = 1;
  186. // Recipe matrix (itemstrings)
  187. std::vector<std::string> recipe;
  188. // Recipe matrix (item names)
  189. std::vector<std::string> recipe_names;
  190. // bool indicating if initHash has been called already
  191. bool hash_inited = false;
  192. // Replacement items for decrementInput()
  193. CraftReplacements replacements;
  194. };
  195. /*
  196. A shapeless crafting definition
  197. Supported crafting method: CRAFT_METHOD_NORMAL.
  198. Input items can arranged in any way.
  199. */
  200. class CraftDefinitionShapeless: public CraftDefinition
  201. {
  202. public:
  203. CraftDefinitionShapeless() = delete;
  204. CraftDefinitionShapeless(
  205. const std::string &output_,
  206. const std::vector<std::string> &recipe_,
  207. const CraftReplacements &replacements_);
  208. virtual ~CraftDefinitionShapeless() = default;
  209. virtual std::string getName() const;
  210. virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
  211. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
  212. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
  213. virtual void decrementInput(CraftInput &input,
  214. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
  215. virtual u64 getHash(CraftHashType type) const;
  216. virtual void initHash(IGameDef *gamedef);
  217. virtual std::string dump() const;
  218. private:
  219. // Output itemstring
  220. std::string output;
  221. // Recipe list (itemstrings)
  222. std::vector<std::string> recipe;
  223. // Recipe list (item names), sorted
  224. std::vector<std::string> recipe_names;
  225. // bool indicating if initHash has been called already
  226. bool hash_inited = false;
  227. // Replacement items for decrementInput()
  228. CraftReplacements replacements;
  229. };
  230. /*
  231. Tool repair crafting definition
  232. Supported crafting method: CRAFT_METHOD_NORMAL.
  233. Put two damaged tools into the crafting grid, get one tool back.
  234. There should only be one crafting definition of this type.
  235. */
  236. class CraftDefinitionToolRepair: public CraftDefinition
  237. {
  238. public:
  239. CraftDefinitionToolRepair() = delete;
  240. CraftDefinitionToolRepair(float additional_wear_);
  241. virtual ~CraftDefinitionToolRepair() = default;
  242. virtual std::string getName() const;
  243. virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
  244. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
  245. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
  246. virtual void decrementInput(CraftInput &input,
  247. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
  248. virtual u64 getHash(CraftHashType type) const { return 2; }
  249. virtual void initHash(IGameDef *gamedef)
  250. {
  251. hash_type = CRAFT_HASH_TYPE_COUNT;
  252. }
  253. virtual std::string dump() const;
  254. private:
  255. // This is a constant that is added to the wear of the result.
  256. // May be positive or negative, allowed range [-1,1].
  257. // 1 = new tool is completely broken
  258. // 0 = simply add remaining uses of both input tools
  259. // -1 = new tool is completely pristine
  260. float additional_wear = 0.0f;
  261. };
  262. /*
  263. A cooking (in furnace) definition
  264. Supported crafting method: CRAFT_METHOD_COOKING.
  265. */
  266. class CraftDefinitionCooking: public CraftDefinition
  267. {
  268. public:
  269. CraftDefinitionCooking() = delete;
  270. CraftDefinitionCooking(
  271. const std::string &output_,
  272. const std::string &recipe_,
  273. float cooktime_,
  274. const CraftReplacements &replacements_);
  275. virtual ~CraftDefinitionCooking() = default;
  276. virtual std::string getName() const;
  277. virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
  278. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
  279. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
  280. virtual void decrementInput(CraftInput &input,
  281. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
  282. virtual u64 getHash(CraftHashType type) const;
  283. virtual void initHash(IGameDef *gamedef);
  284. virtual std::string dump() const;
  285. private:
  286. // Output itemstring
  287. std::string output;
  288. // Recipe itemstring
  289. std::string recipe;
  290. // Recipe item name
  291. std::string recipe_name;
  292. // bool indicating if initHash has been called already
  293. bool hash_inited = false;
  294. // Time in seconds
  295. float cooktime;
  296. // Replacement items for decrementInput()
  297. CraftReplacements replacements;
  298. };
  299. /*
  300. A fuel (for furnace) definition
  301. Supported crafting method: CRAFT_METHOD_FUEL.
  302. */
  303. class CraftDefinitionFuel: public CraftDefinition
  304. {
  305. public:
  306. CraftDefinitionFuel() = delete;
  307. CraftDefinitionFuel(
  308. const std::string &recipe_,
  309. float burntime_,
  310. const CraftReplacements &replacements_);
  311. virtual ~CraftDefinitionFuel() = default;
  312. virtual std::string getName() const;
  313. virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
  314. virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
  315. virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
  316. virtual void decrementInput(CraftInput &input,
  317. std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
  318. virtual u64 getHash(CraftHashType type) const;
  319. virtual void initHash(IGameDef *gamedef);
  320. virtual std::string dump() const;
  321. private:
  322. // Recipe itemstring
  323. std::string recipe;
  324. // Recipe item name
  325. std::string recipe_name;
  326. // bool indicating if initHash has been called already
  327. bool hash_inited = false;
  328. // Time in seconds
  329. float burntime;
  330. // Replacement items for decrementInput()
  331. CraftReplacements replacements;
  332. };
  333. /*
  334. Crafting definition manager
  335. */
  336. class ICraftDefManager
  337. {
  338. public:
  339. ICraftDefManager() = default;
  340. virtual ~ICraftDefManager() = default;
  341. /**
  342. * The main crafting function.
  343. *
  344. * @param input The input grid.
  345. * @param output CraftOutput where the result is placed.
  346. * @param output_replacements A vector of ItemStacks where replacements are
  347. * placed if they cannot be placed in the input. Replacements can be placed
  348. * in the input if the stack of the replaced item has a count of 1.
  349. * @param decrementInput If true, consume or replace input items.
  350. * @param gamedef
  351. * @return true if a result was found, otherwise false.
  352. */
  353. virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
  354. std::vector<ItemStack> &output_replacements,
  355. bool decrementInput, IGameDef *gamedef) const=0;
  356. virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
  357. IGameDef *gamedef, unsigned limit=0) const=0;
  358. // Print crafting recipes for debugging
  359. virtual std::string dump() const=0;
  360. };
  361. class IWritableCraftDefManager : public ICraftDefManager
  362. {
  363. public:
  364. IWritableCraftDefManager() = default;
  365. virtual ~IWritableCraftDefManager() = default;
  366. // The main crafting function
  367. virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
  368. std::vector<ItemStack> &output_replacements,
  369. bool decrementInput, IGameDef *gamedef) const=0;
  370. virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
  371. IGameDef *gamedef, unsigned limit=0) const=0;
  372. virtual bool clearCraftsByOutput(const CraftOutput &output, IGameDef *gamedef) = 0;
  373. virtual bool clearCraftsByInput(const CraftInput &input, IGameDef *gamedef) = 0;
  374. // Print crafting recipes for debugging
  375. virtual std::string dump() const=0;
  376. // Add a crafting definition.
  377. // After calling this, the pointer belongs to the manager.
  378. virtual void registerCraft(CraftDefinition *def, IGameDef *gamedef) = 0;
  379. // Delete all crafting definitions
  380. virtual void clear()=0;
  381. // To be called after all mods are loaded, so that we catch all aliases
  382. virtual void initHashes(IGameDef *gamedef) = 0;
  383. };
  384. IWritableCraftDefManager* createCraftDefManager();