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