X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Flua_api%2Fl_craft.cpp;h=137b210be2a8c13876ef5715b8ed4a06cdaa1f84;hb=7f58887ae33893c981fbdff23d4e1fa4a11c32e4;hp=391a0133d9e1172731dd5a7823499d4816e56f45;hpb=fa1096ec49ee9b2b8ca85ff272930812e657b3c5;p=minetest.git diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index 391a0133d..137b210be 100644 --- a/src/script/lua_api/l_craft.cpp +++ b/src/script/lua_api/l_craft.cpp @@ -34,7 +34,6 @@ struct EnumString ModApiCraft::es_CraftMethod[] = {0, NULL}, }; - // helper for register_craft bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index, int &width, std::vector &recipe) @@ -58,7 +57,7 @@ bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index, // key at index -2 and value at index -1 if(!lua_isstring(L, -1)) return false; - recipe.push_back(lua_tostring(L, -1)); + recipe.emplace_back(readParam(L, -1)); // removes value, keeps key for next iteration lua_pop(L, 1); colcount++; @@ -91,7 +90,7 @@ bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index, // key at index -2 and value at index -1 if(!lua_isstring(L, -1)) return false; - recipe.push_back(lua_tostring(L, -1)); + recipe.emplace_back(readParam(L, -1)); // removes value, keeps key for next iteration lua_pop(L, 1); } @@ -116,15 +115,14 @@ bool ModApiCraft::readCraftReplacements(lua_State *L, int index, lua_rawgeti(L, -1, 1); if(!lua_isstring(L, -1)) return false; - std::string replace_from = lua_tostring(L, -1); + std::string replace_from = readParam(L, -1); lua_pop(L, 1); lua_rawgeti(L, -1, 2); if(!lua_isstring(L, -1)) return false; - std::string replace_to = lua_tostring(L, -1); + std::string replace_to = readParam(L, -1); lua_pop(L, 1); - replacements.pairs.push_back( - std::make_pair(replace_from, replace_to)); + replacements.pairs.emplace_back(replace_from, replace_to); // removes value, keeps key for next iteration lua_pop(L, 1); } @@ -149,7 +147,7 @@ int ModApiCraft::l_register_craft(lua_State *L) */ if(type == "shaped"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") + if (output.empty()) throw LuaError("Crafting definition is missing an output"); int width = 0; @@ -180,7 +178,7 @@ int ModApiCraft::l_register_craft(lua_State *L) */ else if(type == "shapeless"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") + if (output.empty()) throw LuaError("Crafting definition (shapeless)" " is missing an output"); @@ -223,12 +221,12 @@ int ModApiCraft::l_register_craft(lua_State *L) */ else if(type == "cooking"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") + if (output.empty()) throw LuaError("Crafting definition (cooking)" " is missing an output"); std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") + if (recipe.empty()) throw LuaError("Crafting definition (cooking)" " is missing a recipe" " (output=\"" + output + "\")"); @@ -253,7 +251,7 @@ int ModApiCraft::l_register_craft(lua_State *L) */ else if(type == "fuel"){ std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") + if (recipe.empty()) throw LuaError("Crafting definition (fuel)" " is missing a recipe"); @@ -281,12 +279,101 @@ int ModApiCraft::l_register_craft(lua_State *L) return 0; /* number of results */ } +// clear_craft({[output=item], [recipe={{item00,item10},{item01,item11}}]) +int ModApiCraft::l_clear_craft(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + luaL_checktype(L, 1, LUA_TTABLE); + int table = 1; + + // Get the writable craft definition manager from the server + IWritableCraftDefManager *craftdef = + getServer(L)->getWritableCraftDefManager(); + + std::string output = getstringfield_default(L, table, "output", ""); + std::string type = getstringfield_default(L, table, "type", "shaped"); + CraftOutput c_output(output, 0); + if (!output.empty()) { + if (craftdef->clearCraftsByOutput(c_output, getServer(L))) { + lua_pushboolean(L, true); + return 1; + } + + warningstream << "No craft recipe known for output" << std::endl; + lua_pushboolean(L, false); + return 1; + } + std::vector recipe; + int width = 0; + CraftMethod method = CRAFT_METHOD_NORMAL; + /* + CraftDefinitionShaped + */ + if (type == "shaped") { + lua_getfield(L, table, "recipe"); + if (lua_isnil(L, -1)) + throw LuaError("Either output or recipe has to be defined"); + if (!readCraftRecipeShaped(L, -1, width, recipe)) + throw LuaError("Invalid crafting recipe"); + } + /* + CraftDefinitionShapeless + */ + else if (type == "shapeless") { + lua_getfield(L, table, "recipe"); + if (lua_isnil(L, -1)) + throw LuaError("Either output or recipe has to be defined"); + if (!readCraftRecipeShapeless(L, -1, recipe)) + throw LuaError("Invalid crafting recipe"); + } + /* + CraftDefinitionCooking + */ + else if (type == "cooking") { + method = CRAFT_METHOD_COOKING; + std::string rec = getstringfield_default(L, table, "recipe", ""); + if (rec.empty()) + throw LuaError("Crafting definition (cooking)" + " is missing a recipe"); + recipe.push_back(rec); + } + /* + CraftDefinitionFuel + */ + else if (type == "fuel") { + method = CRAFT_METHOD_FUEL; + std::string rec = getstringfield_default(L, table, "recipe", ""); + if (rec.empty()) + throw LuaError("Crafting definition (fuel)" + " is missing a recipe"); + recipe.push_back(rec); + } else { + throw LuaError("Unknown crafting definition type: \"" + type + "\""); + } + + std::vector items; + items.reserve(recipe.size()); + for (const auto &item : recipe) + items.emplace_back(item, 1, 0, getServer(L)->idef()); + CraftInput input(method, width, items); + + if (!craftdef->clearCraftsByInput(input, getServer(L))) { + warningstream << "No craft recipe matches input" << std::endl; + lua_pushboolean(L, false); + return 1; + } + + lua_pushboolean(L, true); + return 1; +} + // get_craft_result(input) int ModApiCraft::l_get_craft_result(lua_State *L) { NO_MAP_LOCK_REQUIRED; + IGameDef *gdef = getGameDef(L); - int input_i = 1; + const int input_i = 1; std::string method_s = getstringfield_default(L, input_i, "method", "normal"); enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method", es_CraftMethod, CRAFT_METHOD_NORMAL); @@ -296,10 +383,9 @@ int ModApiCraft::l_get_craft_result(lua_State *L) width = luaL_checkinteger(L, -1); lua_pop(L, 1); lua_getfield(L, input_i, "items"); - std::vector items = read_items(L, -1,getServer(L)); + std::vector items = read_items(L, -1, gdef); lua_pop(L, 1); // items - IGameDef *gdef = getServer(L); ICraftDefManager *cdef = gdef->cdef(); CraftInput input(method, width, items); CraftOutput output; @@ -341,7 +427,7 @@ static void push_craft_recipe(lua_State *L, IGameDef *gdef, lua_newtable(L); // items std::vector::const_iterator iter = input.items.begin(); - for (u16 j = 1; iter != input.items.end(); iter++, j++) { + for (u16 j = 1; iter != input.items.end(); ++iter, j++) { if (iter->empty()) continue; lua_pushstring(L, iter->name.c_str()); @@ -349,20 +435,28 @@ static void push_craft_recipe(lua_State *L, IGameDef *gdef, } lua_setfield(L, -2, "items"); setintfield(L, -1, "width", input.width); + + std::string method_s; switch (input.method) { case CRAFT_METHOD_NORMAL: - lua_pushstring(L, "normal"); + method_s = "normal"; break; case CRAFT_METHOD_COOKING: - lua_pushstring(L, "cooking"); + method_s = "cooking"; break; case CRAFT_METHOD_FUEL: - lua_pushstring(L, "fuel"); + method_s = "fuel"; break; default: - lua_pushstring(L, "unknown"); + method_s = "unknown"; } + lua_pushstring(L, method_s.c_str()); + lua_setfield(L, -2, "method"); + + // Deprecated, only for compatibility's sake + lua_pushstring(L, method_s.c_str()); lua_setfield(L, -2, "type"); + lua_pushstring(L, output.item.c_str()); lua_setfield(L, -2, "output"); } @@ -371,13 +465,13 @@ static void push_craft_recipes(lua_State *L, IGameDef *gdef, const std::vector &recipes, const CraftOutput &output) { - lua_createtable(L, recipes.size(), 0); - if (recipes.empty()) { lua_pushnil(L); return; } + lua_createtable(L, recipes.size(), 0); + std::vector::const_iterator it = recipes.begin(); for (unsigned i = 0; it != recipes.end(); ++it) { lua_newtable(L); @@ -393,10 +487,9 @@ int ModApiCraft::l_get_craft_recipe(lua_State *L) NO_MAP_LOCK_REQUIRED; std::string item = luaL_checkstring(L, 1); - Server *server = getServer(L); + IGameDef *gdef = getGameDef(L); CraftOutput output(item, 0); - std::vector recipes = server->cdef() - ->getCraftRecipes(output, server, 1); + auto recipes = gdef->cdef()->getCraftRecipes(output, gdef, 1); lua_createtable(L, 1, 0); @@ -406,7 +499,7 @@ int ModApiCraft::l_get_craft_recipe(lua_State *L) setintfield(L, -1, "width", 0); return 1; } - push_craft_recipe(L, server, recipes[0], output); + push_craft_recipe(L, gdef, recipes[0], output); return 1; } @@ -416,12 +509,11 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L) NO_MAP_LOCK_REQUIRED; std::string item = luaL_checkstring(L, 1); - Server *server = getServer(L); + IGameDef *gdef = getGameDef(L); CraftOutput output(item, 0); - std::vector recipes = server->cdef() - ->getCraftRecipes(output, server); + auto recipes = gdef->cdef()->getCraftRecipes(output, gdef); - push_craft_recipes(L, server, recipes, output); + push_craft_recipes(L, gdef, recipes, output); return 1; } @@ -431,4 +523,13 @@ void ModApiCraft::Initialize(lua_State *L, int top) API_FCT(get_craft_recipe); API_FCT(get_craft_result); API_FCT(register_craft); + API_FCT(clear_craft); +} + +void ModApiCraft::InitializeAsync(lua_State *L, int top) +{ + // all read-only functions + API_FCT(get_all_craft_recipes); + API_FCT(get_craft_recipe); + API_FCT(get_craft_result); }