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