Allow replacements in cooking and fuel recipes
[oweals/minetest.git] / src / craftdef.h
1 /*
2 Minetest-c55
3 Copyright (C) 2011 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         Input: The contents of the crafting slots, arranged in matrix form
48 */
49 struct CraftInput
50 {
51         CraftMethod method;
52         unsigned int width;
53         std::vector<ItemStack> items;
54
55         CraftInput():
56                 method(CRAFT_METHOD_NORMAL), width(0), items()
57         {}
58         CraftInput(CraftMethod method_, unsigned int width_,
59                         const std::vector<ItemStack> &items_):
60                 method(method_), width(width_), items(items_)
61         {}
62         std::string dump() const;
63 };
64
65 /*
66         Output: Result of crafting operation
67 */
68 struct CraftOutput
69 {
70         // Used for normal crafting and cooking, itemstring
71         std::string item;
72         // Used for cooking (cook time) and fuel (burn time), seconds
73         float time;
74
75         CraftOutput():
76                 item(""), time(0)
77         {}
78         CraftOutput(std::string item_, float time_):
79                 item(item_), time(time_)
80         {}
81         std::string dump() const;
82 };
83
84 /*
85         A list of replacements. A replacement indicates that a specific
86         input item should not be deleted (when crafting) but replaced with
87         a different item. Each replacements is a pair (itemstring to remove,
88         itemstring to replace with)
89
90         Example: If ("bucket:bucket_water", "bucket:bucket_empty") is a
91         replacement pair, the crafting input slot that contained a water
92         bucket will contain an empty bucket after crafting.
93
94         Note: replacements only work correctly when stack_max of the item
95         to be replaced is 1. It is up to the mod writer to ensure this.
96 */
97 struct CraftReplacements
98 {
99         // List of replacements
100         std::vector<std::pair<std::string, std::string> > pairs;
101
102         CraftReplacements():
103                 pairs()
104         {}
105         CraftReplacements(std::vector<std::pair<std::string, std::string> > pairs_):
106                 pairs(pairs_)
107         {}
108         std::string dump() const;
109         void serialize(std::ostream &os) const;
110         void deSerialize(std::istream &is);
111 };
112
113 /*
114         Crafting definition base class
115 */
116 class CraftDefinition
117 {
118 public:
119         CraftDefinition(){}
120         virtual ~CraftDefinition(){}
121
122         void serialize(std::ostream &os) const;
123         static CraftDefinition* deSerialize(std::istream &is);
124
125         // Returns type of crafting definition
126         virtual std::string getName() const=0;
127
128         // Checks whether the recipe is applicable
129         virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
130         // Returns the output structure, meaning depends on crafting method
131         // The implementation can assume that check(input) returns true
132         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
133         // Decreases count of every input item
134         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
135
136         virtual std::string dump() const=0;
137
138 protected:
139         virtual void serializeBody(std::ostream &os) const=0;
140         virtual void deSerializeBody(std::istream &is, int version)=0;
141 };
142
143 /*
144         A plain-jane (shaped) crafting definition
145
146         Supported crafting method: CRAFT_METHOD_NORMAL.
147         Requires the input items to be arranged exactly like in the recipe.
148 */
149 class CraftDefinitionShaped: public CraftDefinition
150 {
151 public:
152         CraftDefinitionShaped():
153                 output(""), width(1), recipe(), replacements()
154         {}
155         CraftDefinitionShaped(
156                         const std::string &output_,
157                         unsigned int width_,
158                         const std::vector<std::string> &recipe_,
159                         const CraftReplacements &replacements_):
160                 output(output_), width(width_), recipe(recipe_), replacements(replacements_)
161         {}
162         virtual ~CraftDefinitionShaped(){}
163
164         virtual std::string getName() const;
165         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
166         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
167         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
168
169         virtual std::string dump() const;
170
171 protected:
172         virtual void serializeBody(std::ostream &os) const;
173         virtual void deSerializeBody(std::istream &is, int version);
174
175 private:
176         // Output itemstring
177         std::string output;
178         // Width of recipe
179         unsigned int width;
180         // Recipe matrix (itemstrings)
181         std::vector<std::string> recipe;
182         // Replacement items for decrementInput()
183         CraftReplacements replacements;
184 };
185
186 /*
187         A shapeless crafting definition
188         Supported crafting method: CRAFT_METHOD_NORMAL.
189         Input items can arranged in any way.
190 */
191 class CraftDefinitionShapeless: public CraftDefinition
192 {
193 public:
194         CraftDefinitionShapeless():
195                 output(""), recipe(), replacements()
196         {}
197         CraftDefinitionShapeless(
198                         const std::string &output_,
199                         const std::vector<std::string> &recipe_,
200                         const CraftReplacements &replacements_):
201                 output(output_), recipe(recipe_), replacements(replacements_)
202         {}
203         virtual ~CraftDefinitionShapeless(){}
204
205         virtual std::string getName() const;
206         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
207         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
208         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
209
210         virtual std::string dump() const;
211
212 protected:
213         virtual void serializeBody(std::ostream &os) const;
214         virtual void deSerializeBody(std::istream &is, int version);
215
216 private:
217         // Output itemstring
218         std::string output;
219         // Recipe list (itemstrings)
220         std::vector<std::string> recipe;
221         // Replacement items for decrementInput()
222         CraftReplacements replacements;
223 };
224
225 /*
226         Tool repair crafting definition
227         Supported crafting method: CRAFT_METHOD_NORMAL.
228         Put two damaged tools into the crafting grid, get one tool back.
229         There should only be one crafting definition of this type.
230 */
231 class CraftDefinitionToolRepair: public CraftDefinition
232 {
233 public:
234         CraftDefinitionToolRepair():
235                 additional_wear(0)
236         {}
237         CraftDefinitionToolRepair(float additional_wear_):
238                 additional_wear(additional_wear_)
239         {}
240         virtual ~CraftDefinitionToolRepair(){}
241
242         virtual std::string getName() const;
243         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
244         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
245         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
246
247         virtual std::string dump() const;
248
249 protected:
250         virtual void serializeBody(std::ostream &os) const;
251         virtual void deSerializeBody(std::istream &is, int version);
252
253 private:
254         // This is a constant that is added to the wear of the result.
255         // May be positive or negative, allowed range [-1,1].
256         // 1 = new tool is completely broken
257         // 0 = simply add remaining uses of both input tools
258         // -1 = new tool is completely pristine
259         float additional_wear;
260 };
261
262 /*
263         A cooking (in furnace) definition
264         Supported crafting method: CRAFT_METHOD_COOKING.
265 */
266 class CraftDefinitionCooking: public CraftDefinition
267 {
268 public:
269         CraftDefinitionCooking():
270                 output(""), recipe(""), cooktime()
271         {}
272         CraftDefinitionCooking(
273                         const std::string &output_,
274                         const std::string &recipe_,
275                         float cooktime_,
276                         const CraftReplacements &replacements_):
277                 output(output_), recipe(recipe_), cooktime(cooktime_), replacements(replacements_)
278         {}
279         virtual ~CraftDefinitionCooking(){}
280
281         virtual std::string getName() const;
282         virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
283         virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
284         virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
285
286         virtual std::string dump() const;
287
288 protected:
289         virtual void serializeBody(std::ostream &os) const;
290         virtual void deSerializeBody(std::istream &is, int version);
291
292 private:
293         // Output itemstring
294         std::string output;
295         // Recipe itemstring
296         std::string recipe;
297         // Time in seconds
298         float cooktime;
299         // Replacement items for decrementInput()
300         CraftReplacements replacements;
301 };
302
303 /*
304         A fuel (for furnace) definition
305         Supported crafting method: CRAFT_METHOD_FUEL.
306 */
307 class CraftDefinitionFuel: public CraftDefinition
308 {
309 public:
310         CraftDefinitionFuel():
311                 recipe(""), burntime()
312         {}
313         CraftDefinitionFuel(std::string recipe_,
314                         float burntime_,
315                         const CraftReplacements &replacements_):
316                 recipe(recipe_), burntime(burntime_), replacements(replacements_)
317         {}
318         virtual ~CraftDefinitionFuel(){}
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 void decrementInput(CraftInput &input, IGameDef *gamedef) const;
324
325         virtual std::string dump() const;
326
327 protected:
328         virtual void serializeBody(std::ostream &os) const;
329         virtual void deSerializeBody(std::istream &is, int version);
330
331 private:
332         // Recipe itemstring
333         std::string recipe;
334         // Time in seconds
335         float burntime;
336         // Replacement items for decrementInput()
337         CraftReplacements replacements;
338 };
339
340 /*
341         Crafting definition manager
342 */
343 class ICraftDefManager
344 {
345 public:
346         ICraftDefManager(){}
347         virtual ~ICraftDefManager(){}
348
349         // The main crafting function
350         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
351                         bool decrementInput, IGameDef *gamedef) const=0;
352         
353         // Print crafting recipes for debugging
354         virtual std::string dump() const=0;
355
356         virtual void serialize(std::ostream &os) const=0;
357 };
358
359 class IWritableCraftDefManager : public ICraftDefManager
360 {
361 public:
362         IWritableCraftDefManager(){}
363         virtual ~IWritableCraftDefManager(){}
364
365         // The main crafting function
366         virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
367                         bool decrementInput, IGameDef *gamedef) const=0;
368
369         // Print crafting recipes for debugging
370         virtual std::string dump() const=0;
371
372         // Add a crafting definition.
373         // After calling this, the pointer belongs to the manager.
374         virtual void registerCraft(CraftDefinition *def)=0;
375         // Delete all crafting definitions
376         virtual void clear()=0;
377
378         virtual void serialize(std::ostream &os) const=0;
379         virtual void deSerialize(std::istream &is)=0;
380 };
381
382 IWritableCraftDefManager* createCraftDefManager();
383
384 #endif
385