Remove craftdef serialisation
[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;
74         unsigned int width;
75         std::vector<ItemStack> items;
76
77         CraftInput():
78                 method(CRAFT_METHOD_NORMAL), width(0), items()
79         {}
80         CraftInput(CraftMethod method_, unsigned int width_,
81                         const std::vector<ItemStack> &items_):
82                 method(method_), width(width_), items(items_)
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;
96
97         CraftOutput():
98                 item(""), time(0)
99         {}
100         CraftOutput(std::string item_, float time_):
101                 item(item_), time(time_)
102         {}
103         std::string dump() const;
104 };
105
106 /*
107         A list of replacements. A replacement indicates that a specific
108         input item should not be deleted (when crafting) but replaced with
109         a different item. Each replacements is a pair (itemstring to remove,
110         itemstring to replace with)
111
112         Example: If ("bucket:bucket_water", "bucket:bucket_empty") is a
113         replacement pair, the crafting input slot that contained a water
114         bucket will contain an empty bucket after crafting.
115
116         Note: replacements only work correctly when stack_max of the item
117         to be replaced is 1. It is up to the mod writer to ensure this.
118 */
119 struct CraftReplacements
120 {
121         // List of replacements
122         std::vector<std::pair<std::string, std::string> > pairs;
123
124         CraftReplacements():
125                 pairs()
126         {}
127         CraftReplacements(std::vector<std::pair<std::string, std::string> > pairs_):
128                 pairs(pairs_)
129         {}
130         std::string dump() const;
131 };
132
133 /*
134         Crafting definition base class
135 */
136 class CraftDefinition
137 {
138 public:
139         CraftDefinition(){}
140         virtual ~CraftDefinition(){}
141
142         // Returns type of crafting definition
143         virtual std::string getName() const=0;
144
145         // Checks whether the recipe is applicable
146         virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
147         // Returns the output structure, meaning depends on crafting method
148         // The implementation can assume that check(input) returns true
149         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
150         // the inverse of the above
151         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
152         // Decreases count of every input item
153         virtual void decrementInput(CraftInput &input, 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                 output(""), width(1), recipe(), hash_inited(false), replacements()
175         {}
176         CraftDefinitionShaped(
177                         const std::string &output_,
178                         unsigned int width_,
179                         const std::vector<std::string> &recipe_,
180                         const CraftReplacements &replacements_):
181                 output(output_), width(width_), recipe(recipe_),
182                 hash_inited(false), replacements(replacements_)
183         {}
184         virtual ~CraftDefinitionShaped(){}
185
186         virtual std::string getName() const;
187         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
188         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
189         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
190         virtual void decrementInput(CraftInput &input, 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;
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;
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, 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, IGameDef *gamedef) const;
282
283         virtual CraftHashType getHashType() const { return CRAFT_HASH_TYPE_COUNT; }
284         virtual u64 getHash(CraftHashType type) const { return 2; }
285
286         virtual void initHash(IGameDef *gamedef) {}
287
288         virtual std::string dump() const;
289
290 private:
291         // This is a constant that is added to the wear of the result.
292         // May be positive or negative, allowed range [-1,1].
293         // 1 = new tool is completely broken
294         // 0 = simply add remaining uses of both input tools
295         // -1 = new tool is completely pristine
296         float additional_wear;
297 };
298
299 /*
300         A cooking (in furnace) definition
301         Supported crafting method: CRAFT_METHOD_COOKING.
302 */
303 class CraftDefinitionCooking: public CraftDefinition
304 {
305 public:
306         CraftDefinitionCooking():
307                 output(""), recipe(""), hash_inited(false), cooktime()
308         {}
309         CraftDefinitionCooking(
310                         const std::string &output_,
311                         const std::string &recipe_,
312                         float cooktime_,
313                         const CraftReplacements &replacements_):
314                 output(output_), recipe(recipe_), hash_inited(false),
315                 cooktime(cooktime_), replacements(replacements_)
316         {}
317         virtual ~CraftDefinitionCooking(){}
318
319         virtual std::string getName() const;
320         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
321         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
322         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
323         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
324
325         virtual CraftHashType getHashType() const;
326         virtual u64 getHash(CraftHashType type) const;
327
328         virtual void initHash(IGameDef *gamedef);
329
330         virtual std::string dump() const;
331
332 private:
333         // Output itemstring
334         std::string output;
335         // Recipe itemstring
336         std::string recipe;
337         // Recipe item name
338         std::string recipe_name;
339         // bool indicating if initHash has been called already
340         bool hash_inited;
341         // Time in seconds
342         float cooktime;
343         // Replacement items for decrementInput()
344         CraftReplacements replacements;
345 };
346
347 /*
348         A fuel (for furnace) definition
349         Supported crafting method: CRAFT_METHOD_FUEL.
350 */
351 class CraftDefinitionFuel: public CraftDefinition
352 {
353 public:
354         CraftDefinitionFuel():
355                 recipe(""), hash_inited(false), burntime()
356         {}
357         CraftDefinitionFuel(std::string recipe_,
358                         float burntime_,
359                         const CraftReplacements &replacements_):
360                 recipe(recipe_), hash_inited(false), burntime(burntime_), replacements(replacements_)
361         {}
362         virtual ~CraftDefinitionFuel(){}
363
364         virtual std::string getName() const;
365         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
366         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
367         virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
368         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
369
370         virtual CraftHashType getHashType() const;
371         virtual u64 getHash(CraftHashType type) const;
372
373         virtual void initHash(IGameDef *gamedef);
374
375         virtual std::string dump() const;
376
377 private:
378         // Recipe itemstring
379         std::string recipe;
380         // Recipe item name
381         std::string recipe_name;
382         // bool indicating if initHash has been called already
383         bool hash_inited;
384         // Time in seconds
385         float burntime;
386         // Replacement items for decrementInput()
387         CraftReplacements replacements;
388 };
389
390 /*
391         Crafting definition manager
392 */
393 class ICraftDefManager
394 {
395 public:
396         ICraftDefManager(){}
397         virtual ~ICraftDefManager(){}
398
399         // The main crafting function
400         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
401                         bool decrementInput, IGameDef *gamedef) const=0;
402         virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
403                         IGameDef *gamedef, unsigned limit=0) const=0;
404
405         // Print crafting recipes for debugging
406         virtual std::string dump() const=0;
407 };
408
409 class IWritableCraftDefManager : public ICraftDefManager
410 {
411 public:
412         IWritableCraftDefManager(){}
413         virtual ~IWritableCraftDefManager(){}
414
415         // The main crafting function
416         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
417                         bool decrementInput, IGameDef *gamedef) const=0;
418         virtual std::vector<CraftDefinition*> getCraftRecipes(CraftOutput &output,
419                         IGameDef *gamedef, unsigned limit=0) const=0;
420
421         // Print crafting recipes for debugging
422         virtual std::string dump() const=0;
423
424         // Add a crafting definition.
425         // After calling this, the pointer belongs to the manager.
426         virtual void registerCraft(CraftDefinition *def, IGameDef *gamedef) = 0;
427
428         // Delete all crafting definitions
429         virtual void clear()=0;
430
431         // To be called after all mods are loaded, so that we catch all aliases
432         virtual void initHashes(IGameDef *gamedef) = 0;
433 };
434
435 IWritableCraftDefManager* createCraftDefManager();
436
437 #endif
438