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