Add minetest.get_craft_recipe()
parent
08e1d40d6e
commit
38580fbee7
|
@ -829,6 +829,13 @@ minetest.get_craft_result(input) -> output, decremented_input
|
||||||
^ output.item = ItemStack, if unsuccessful: empty ItemStack
|
^ output.item = ItemStack, if unsuccessful: empty ItemStack
|
||||||
^ output.time = number, if unsuccessful: 0
|
^ output.time = number, if unsuccessful: 0
|
||||||
^ decremented_input = like input
|
^ decremented_input = like input
|
||||||
|
minetest.get_craft_recipe(output) -> input
|
||||||
|
^ output is a node or item type such as 'default:torch'
|
||||||
|
^ input.method = 'normal' or 'cooking' or 'fuel'
|
||||||
|
^ input.width = for example 3
|
||||||
|
^ input.items = for example { stack 1, stack 2, stack 3, stack 4,
|
||||||
|
stack 5, stack 6, stack 7, stack 8, stack 9 }
|
||||||
|
^ input.items = nil if no recipe found
|
||||||
|
|
||||||
Defaults for the on_* item definition functions:
|
Defaults for the on_* item definition functions:
|
||||||
(These return the leftover itemstack)
|
(These return the leftover itemstack)
|
||||||
|
|
|
@ -35,7 +35,7 @@ static bool inputItemMatchesRecipe(const std::string &inp_name,
|
||||||
// Exact name
|
// Exact name
|
||||||
if(inp_name == rec_name)
|
if(inp_name == rec_name)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Group
|
// Group
|
||||||
if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
|
if(rec_name.substr(0,6) == "group:" && idef->isKnown(inp_name)){
|
||||||
std::string rec_group = rec_name.substr(6);
|
std::string rec_group = rec_name.substr(6);
|
||||||
|
@ -43,7 +43,7 @@ static bool inputItemMatchesRecipe(const std::string &inp_name,
|
||||||
if(itemgroup_get(def.groups, rec_group) != 0)
|
if(itemgroup_get(def.groups, rec_group) != 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Didn't match
|
// Didn't match
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,20 @@ static std::vector<std::string> craftGetItemNames(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert a list of item names, to ItemStacks.
|
||||||
|
static std::vector<ItemStack> craftGetItems(
|
||||||
|
const std::vector<std::string> &items, IGameDef *gamedef)
|
||||||
|
{
|
||||||
|
std::vector<ItemStack> result;
|
||||||
|
for(std::vector<std::string>::const_iterator
|
||||||
|
i = items.begin();
|
||||||
|
i != items.end(); i++)
|
||||||
|
{
|
||||||
|
result.push_back(ItemStack(std::string(*i),(u16)1,(u16)0,"",gamedef->getItemDefManager()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute bounding rectangle given a matrix of items
|
// Compute bounding rectangle given a matrix of items
|
||||||
// Returns false if every item is ""
|
// Returns false if every item is ""
|
||||||
static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
|
static bool craftGetBounds(const std::vector<std::string> &items, unsigned int width,
|
||||||
|
@ -439,6 +453,11 @@ CraftOutput CraftDefinitionShaped::getOutput(const CraftInput &input, IGameDef *
|
||||||
return CraftOutput(output, 0);
|
return CraftOutput(output, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CraftInput CraftDefinitionShaped::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
return CraftInput(CRAFT_METHOD_NORMAL,width,craftGetItems(recipe,gamedef));
|
||||||
|
}
|
||||||
|
|
||||||
void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
void CraftDefinitionShaped::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||||
{
|
{
|
||||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||||
|
@ -507,6 +526,11 @@ CraftOutput CraftDefinitionShapeless::getOutput(const CraftInput &input, IGameDe
|
||||||
return CraftOutput(output, 0);
|
return CraftOutput(output, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CraftInput CraftDefinitionShapeless::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
return CraftInput(CRAFT_METHOD_NORMAL,0,craftGetItems(recipe,gamedef));
|
||||||
|
}
|
||||||
|
|
||||||
void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
void CraftDefinitionShapeless::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||||
{
|
{
|
||||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||||
|
@ -625,6 +649,13 @@ CraftOutput CraftDefinitionToolRepair::getOutput(const CraftInput &input, IGameD
|
||||||
return CraftOutput(repaired.getItemString(), 0);
|
return CraftOutput(repaired.getItemString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CraftInput CraftDefinitionToolRepair::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
std::vector<ItemStack> stack;
|
||||||
|
stack.push_back(ItemStack());
|
||||||
|
return CraftInput(CRAFT_METHOD_COOKING,additional_wear,stack);
|
||||||
|
}
|
||||||
|
|
||||||
void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
void CraftDefinitionToolRepair::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||||
{
|
{
|
||||||
craftDecrementInput(input, gamedef);
|
craftDecrementInput(input, gamedef);
|
||||||
|
@ -680,6 +711,13 @@ CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef
|
||||||
return CraftOutput(output, cooktime);
|
return CraftOutput(output, cooktime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CraftInput CraftDefinitionCooking::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
std::vector<std::string> rec;
|
||||||
|
rec.push_back(recipe);
|
||||||
|
return CraftInput(CRAFT_METHOD_COOKING,cooktime,craftGetItems(rec,gamedef));
|
||||||
|
}
|
||||||
|
|
||||||
void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||||
{
|
{
|
||||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||||
|
@ -744,6 +782,13 @@ CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *ga
|
||||||
return CraftOutput("", burntime);
|
return CraftOutput("", burntime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CraftInput CraftDefinitionFuel::getInput(const CraftOutput &output, IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
std::vector<std::string> rec;
|
||||||
|
rec.push_back(recipe);
|
||||||
|
return CraftInput(CRAFT_METHOD_COOKING,(int)burntime,craftGetItems(rec,gamedef));
|
||||||
|
}
|
||||||
|
|
||||||
void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
|
||||||
{
|
{
|
||||||
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
craftDecrementOrReplaceInput(input, replacements, gamedef);
|
||||||
|
@ -837,6 +882,47 @@ public:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||||
|
IGameDef *gamedef) const
|
||||||
|
{
|
||||||
|
CraftOutput tmpout;
|
||||||
|
tmpout.item = "";
|
||||||
|
tmpout.time = 0;
|
||||||
|
|
||||||
|
// If output item is empty, abort.
|
||||||
|
if(output.item.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Walk crafting definitions from back to front, so that later
|
||||||
|
// definitions can override earlier ones.
|
||||||
|
for(std::vector<CraftDefinition*>::const_reverse_iterator
|
||||||
|
i = m_craft_definitions.rbegin();
|
||||||
|
i != m_craft_definitions.rend(); i++)
|
||||||
|
{
|
||||||
|
CraftDefinition *def = *i;
|
||||||
|
|
||||||
|
/*infostream<<"Checking "<<input.dump()<<std::endl
|
||||||
|
<<" against "<<def->dump()<<std::endl;*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
tmpout = def->getOutput(input, gamedef);
|
||||||
|
if(tmpout.item.substr(0,output.item.length()) == output.item)
|
||||||
|
{
|
||||||
|
// Get output, then decrement input (if requested)
|
||||||
|
input = def->getInput(output, gamedef);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
errorstream<<"getCraftResult: ERROR: "
|
||||||
|
<<"Serialization error in recipe "
|
||||||
|
<<def->dump()<<std::endl;
|
||||||
|
// then go on with the next craft definition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
virtual std::string dump() const
|
virtual std::string dump() const
|
||||||
{
|
{
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
|
|
|
@ -130,6 +130,8 @@ public:
|
||||||
// Returns the output structure, meaning depends on crafting method
|
// Returns the output structure, meaning depends on crafting method
|
||||||
// The implementation can assume that check(input) returns true
|
// The implementation can assume that check(input) returns true
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
|
||||||
|
// the inverse of the above
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const=0;
|
||||||
// Decreases count of every input item
|
// Decreases count of every input item
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;
|
||||||
|
|
||||||
|
@ -164,6 +166,7 @@ public:
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
@ -205,6 +208,7 @@ public:
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
@ -242,6 +246,7 @@ public:
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
@ -281,6 +286,7 @@ public:
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
@ -320,6 +326,7 @@ public:
|
||||||
virtual std::string getName() const;
|
virtual std::string getName() const;
|
||||||
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
virtual CraftInput getInput(const CraftOutput &output, IGameDef *gamedef) const;
|
||||||
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;
|
||||||
|
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
|
@ -349,6 +356,8 @@ public:
|
||||||
// The main crafting function
|
// The main crafting function
|
||||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||||
bool decrementInput, IGameDef *gamedef) const=0;
|
bool decrementInput, IGameDef *gamedef) const=0;
|
||||||
|
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
|
||||||
// Print crafting recipes for debugging
|
// Print crafting recipes for debugging
|
||||||
virtual std::string dump() const=0;
|
virtual std::string dump() const=0;
|
||||||
|
@ -365,6 +374,8 @@ public:
|
||||||
// The main crafting function
|
// The main crafting function
|
||||||
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
|
||||||
bool decrementInput, IGameDef *gamedef) const=0;
|
bool decrementInput, IGameDef *gamedef) const=0;
|
||||||
|
virtual bool getCraftRecipe(CraftInput &input, CraftOutput &output,
|
||||||
|
IGameDef *gamedef) const=0;
|
||||||
|
|
||||||
// Print crafting recipes for debugging
|
// Print crafting recipes for debugging
|
||||||
virtual std::string dump() const=0;
|
virtual std::string dump() const=0;
|
||||||
|
|
|
@ -4558,6 +4558,59 @@ static int l_get_craft_result(lua_State *L)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_craft_recipe(result item)
|
||||||
|
static int l_get_craft_recipe(lua_State *L)
|
||||||
|
{
|
||||||
|
int k = 0;
|
||||||
|
char tmp[20];
|
||||||
|
int input_i = 1;
|
||||||
|
std::string o_item = luaL_checkstring(L,input_i);
|
||||||
|
|
||||||
|
IGameDef *gdef = get_server(L);
|
||||||
|
ICraftDefManager *cdef = gdef->cdef();
|
||||||
|
CraftInput input;
|
||||||
|
CraftOutput output(o_item,0);
|
||||||
|
bool got = cdef->getCraftRecipe(input, output, gdef);
|
||||||
|
lua_newtable(L); // output table
|
||||||
|
if(got){
|
||||||
|
lua_newtable(L);
|
||||||
|
for(std::vector<ItemStack>::const_iterator
|
||||||
|
i = input.items.begin();
|
||||||
|
i != input.items.end(); i++, k++)
|
||||||
|
{
|
||||||
|
if (i->empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sprintf(tmp,"%d",k);
|
||||||
|
lua_pushstring(L,tmp);
|
||||||
|
lua_pushstring(L,i->name.c_str());
|
||||||
|
lua_settable(L, -3);
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "items");
|
||||||
|
setintfield(L, -1, "width", input.width);
|
||||||
|
switch (input.method) {
|
||||||
|
case CRAFT_METHOD_NORMAL:
|
||||||
|
lua_pushstring(L,"noraml");
|
||||||
|
break;
|
||||||
|
case CRAFT_METHOD_COOKING:
|
||||||
|
lua_pushstring(L,"cooking");
|
||||||
|
break;
|
||||||
|
case CRAFT_METHOD_FUEL:
|
||||||
|
lua_pushstring(L,"fuel");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lua_pushstring(L,"unknown");
|
||||||
|
}
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
} else {
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_setfield(L, -2, "items");
|
||||||
|
setintfield(L, -1, "width", 0);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct luaL_Reg minetest_f [] = {
|
static const struct luaL_Reg minetest_f [] = {
|
||||||
{"debug", l_debug},
|
{"debug", l_debug},
|
||||||
{"log", l_log},
|
{"log", l_log},
|
||||||
|
@ -4582,6 +4635,7 @@ static const struct luaL_Reg minetest_f [] = {
|
||||||
{"get_password_hash", l_get_password_hash},
|
{"get_password_hash", l_get_password_hash},
|
||||||
{"notify_authentication_modified", l_notify_authentication_modified},
|
{"notify_authentication_modified", l_notify_authentication_modified},
|
||||||
{"get_craft_result", l_get_craft_result},
|
{"get_craft_result", l_get_craft_result},
|
||||||
|
{"get_craft_recipe", l_get_craft_recipe},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue