Modernize src/c* src/d* and src/e* files (#6263)
[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() = default;
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() = default;
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() = default;
123         CraftReplacements(const std::vector<std::pair<std::string, std::string> > &pairs_):
124                 pairs(pairs_)
125         {}
126         std::string dump() const;
127 };
128
129 /*
130         Crafting definition base class
131 */
132 class CraftDefinition
133 {
134 public:
135         CraftDefinition() = default;
136         virtual ~CraftDefinition() = default;
137
138         // Returns type of crafting definition
139         virtual std::string getName() const=0;
140
141         // Checks whether the recipe is applicable
142         virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
143         // Returns the output structure, meaning depends on crafting method
144         // The implementation can assume that check(input) returns true
145         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
146         // the inverse of the above
147         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
148         // Decreases count of every input item
149         virtual void decrementInput(CraftInput &input,
150                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const=0;
151
152         virtual CraftHashType getHashType() const = 0;
153         virtual u64 getHash(CraftHashType type) const = 0;
154
155         // to be called after all mods are loaded, so that we catch all aliases
156         virtual void initHash(IGameDef *gamedef) = 0;
157
158         virtual std::string dump() const=0;
159 };
160
161 /*
162         A plain-jane (shaped) crafting definition
163
164         Supported crafting method: CRAFT_METHOD_NORMAL.
165         Requires the input items to be arranged exactly like in the recipe.
166 */
167 class CraftDefinitionShaped: public CraftDefinition
168 {
169 public:
170         CraftDefinitionShaped() = delete;
171
172         CraftDefinitionShaped(
173                         const std::string &output_,
174                         unsigned int width_,
175                         const std::vector<std::string> &recipe_,
176                         const CraftReplacements &replacements_):
177                 output(output_), width(width_), recipe(recipe_),
178                 replacements(replacements_)
179         {}
180         virtual ~CraftDefinitionShaped() = default;
181
182         virtual std::string getName() const;
183         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
184         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
185         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
186         virtual void decrementInput(CraftInput &input,
187                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
188
189         virtual CraftHashType getHashType() const;
190         virtual u64 getHash(CraftHashType type) const;
191
192         virtual void initHash(IGameDef *gamedef);
193
194         virtual std::string dump() const;
195
196 private:
197         // Output itemstring
198         std::string output = "";
199         // Width of recipe
200         unsigned int width = 1;
201         // Recipe matrix (itemstrings)
202         std::vector<std::string> recipe;
203         // Recipe matrix (item names)
204         std::vector<std::string> recipe_names;
205         // bool indicating if initHash has been called already
206         bool hash_inited = false;
207         // Replacement items for decrementInput()
208         CraftReplacements replacements;
209 };
210
211 /*
212         A shapeless crafting definition
213         Supported crafting method: CRAFT_METHOD_NORMAL.
214         Input items can arranged in any way.
215 */
216 class CraftDefinitionShapeless: public CraftDefinition
217 {
218 public:
219         CraftDefinitionShapeless() = delete;
220         CraftDefinitionShapeless(
221                         const std::string &output_,
222                         const std::vector<std::string> &recipe_,
223                         const CraftReplacements &replacements_):
224                 output(output_), recipe(recipe_), replacements(replacements_)
225         {}
226         virtual ~CraftDefinitionShapeless() = default;
227
228         virtual std::string getName() const;
229         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
230         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
231         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
232         virtual void decrementInput(CraftInput &input,
233                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
234
235         virtual CraftHashType getHashType() const;
236         virtual u64 getHash(CraftHashType type) const;
237
238         virtual void initHash(IGameDef *gamedef);
239
240         virtual std::string dump() const;
241
242 private:
243         // Output itemstring
244         std::string output;
245         // Recipe list (itemstrings)
246         std::vector<std::string> recipe;
247         // Recipe list (item names)
248         std::vector<std::string> recipe_names;
249         // bool indicating if initHash has been called already
250         bool hash_inited = false;
251         // Replacement items for decrementInput()
252         CraftReplacements replacements;
253 };
254
255 /*
256         Tool repair crafting definition
257         Supported crafting method: CRAFT_METHOD_NORMAL.
258         Put two damaged tools into the crafting grid, get one tool back.
259         There should only be one crafting definition of this type.
260 */
261 class CraftDefinitionToolRepair: public CraftDefinition
262 {
263 public:
264         CraftDefinitionToolRepair() = delete;
265         CraftDefinitionToolRepair(float additional_wear_):
266                 additional_wear(additional_wear_)
267         {}
268         virtual ~CraftDefinitionToolRepair() = default;
269
270         virtual std::string getName() const;
271         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
272         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
273         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
274         virtual void decrementInput(CraftInput &input,
275                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
276
277         virtual CraftHashType getHashType() const { return CRAFT_HASH_TYPE_COUNT; }
278         virtual u64 getHash(CraftHashType type) const { return 2; }
279
280         virtual void initHash(IGameDef *gamedef) {}
281
282         virtual std::string dump() const;
283
284 private:
285         // This is a constant that is added to the wear of the result.
286         // May be positive or negative, allowed range [-1,1].
287         // 1 = new tool is completely broken
288         // 0 = simply add remaining uses of both input tools
289         // -1 = new tool is completely pristine
290         float additional_wear = 0.0f;
291 };
292
293 /*
294         A cooking (in furnace) definition
295         Supported crafting method: CRAFT_METHOD_COOKING.
296 */
297 class CraftDefinitionCooking: public CraftDefinition
298 {
299 public:
300         CraftDefinitionCooking() = delete;
301         CraftDefinitionCooking(
302                         const std::string &output_,
303                         const std::string &recipe_,
304                         float cooktime_,
305                         const CraftReplacements &replacements_):
306                 output(output_), recipe(recipe_), cooktime(cooktime_), replacements(replacements_)
307         {}
308         virtual ~CraftDefinitionCooking() = default;
309
310         virtual std::string getName() const;
311         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
312         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
313         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
314         virtual void decrementInput(CraftInput &input,
315                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
316
317         virtual CraftHashType getHashType() const;
318         virtual u64 getHash(CraftHashType type) const;
319
320         virtual void initHash(IGameDef *gamedef);
321
322         virtual std::string dump() const;
323
324 private:
325         // Output itemstring
326         std::string output;
327         // Recipe itemstring
328         std::string recipe;
329         // Recipe item name
330         std::string recipe_name;
331         // bool indicating if initHash has been called already
332         bool hash_inited = false;
333         // Time in seconds
334         float cooktime;
335         // Replacement items for decrementInput()
336         CraftReplacements replacements;
337 };
338
339 /*
340         A fuel (for furnace) definition
341         Supported crafting method: CRAFT_METHOD_FUEL.
342 */
343 class CraftDefinitionFuel: public CraftDefinition
344 {
345 public:
346         CraftDefinitionFuel() = delete;
347         CraftDefinitionFuel(const std::string &recipe_,
348                         float burntime_,
349                         const CraftReplacements &replacements_):
350                 recipe(recipe_), burntime(burntime_), replacements(replacements_)
351         {}
352         virtual ~CraftDefinitionFuel() = default;
353
354         virtual std::string getName() const;
355         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
356         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
357         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
358         virtual void decrementInput(CraftInput &input,
359                 std::vector<ItemStack> &output_replacements, IGameDef *gamedef) const;
360
361         virtual CraftHashType getHashType() const;
362         virtual u64 getHash(CraftHashType type) const;
363
364         virtual void initHash(IGameDef *gamedef);
365
366         virtual std::string dump() const;
367
368 private:
369         // Recipe itemstring
370         std::string recipe;
371         // Recipe item name
372         std::string recipe_name;
373         // bool indicating if initHash has been called already
374         bool hash_inited = false;
375         // Time in seconds
376         float burntime;
377         // Replacement items for decrementInput()
378         CraftReplacements replacements;
379 };
380
381 /*
382         Crafting definition manager
383 */
384 class ICraftDefManager
385 {
386 public:
387         ICraftDefManager() = default;
388         virtual ~ICraftDefManager() = default;
389
390         // The main crafting function
391         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
392                         std::vector<ItemStack> &output_replacements,
393                         bool decrementInput, IGameDef *gamedef) const=0;
394         virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
395                         IGameDef *gamedef, unsigned limit=0) const=0;
396
397         // Print crafting recipes for debugging
398         virtual std::string dump() const=0;
399 };
400
401 class IWritableCraftDefManager : public ICraftDefManager
402 {
403 public:
404         IWritableCraftDefManager() = default;
405         virtual ~IWritableCraftDefManager() = default;
406
407         // The main crafting function
408         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
409                         std::vector<ItemStack> &output_replacements,
410                         bool decrementInput, IGameDef *gamedef) const=0;
411         virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
412                         IGameDef *gamedef, unsigned limit=0) const=0;
413
414         virtual bool clearCraftRecipesByOutput(const CraftOutput &output, IGameDef *gamedef) = 0;
415         virtual bool clearCraftRecipesByInput(CraftMethod craft_method,
416                         unsigned int craft_grid_width, const std::vector<std::string> &recipe, IGameDef *gamedef) = 0;
417
418         // Print crafting recipes for debugging
419         virtual std::string dump() const=0;
420
421         // Add a crafting definition.
422         // After calling this, the pointer belongs to the manager.
423         virtual void registerCraft(CraftDefinition *def, IGameDef *gamedef) = 0;
424
425         // Delete all crafting definitions
426         virtual void clear()=0;
427
428         // To be called after all mods are loaded, so that we catch all aliases
429         virtual void initHashes(IGameDef *gamedef) = 0;
430 };
431
432 IWritableCraftDefManager* createCraftDefManager();