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