X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Flua_api%2Fl_craft.cpp;h=18622ee00826faf939986a6a29e32fb233788cbc;hb=a87805a9445f280ca71da322c4b32cf357744511;hp=240aa045c69d71acc081924bbe54fcb8e63ef5d8;hpb=362ef5f6ced862daa4733034810d0b07e2ad5d89;p=dragonfireclient.git diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index 240aa045c..18622ee00 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,17 +147,17 @@ int ModApiCraft::l_register_craft(lua_State *L) */ if(type == "shaped"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition is missing an output"); + if (output.empty()) + throw LuaError("Crafting definition is missing an output"); int width = 0; std::vector recipe; lua_getfield(L, table, "recipe"); if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition is missing a recipe" + throw LuaError("Crafting definition is missing a recipe" " (output=\"" + output + "\")"); if(!readCraftRecipeShaped(L, -1, width, recipe)) - throw LuaError(L, "Invalid crafting recipe" + throw LuaError("Invalid crafting recipe" " (output=\"" + output + "\")"); CraftReplacements replacements; @@ -167,31 +165,31 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError("Invalid replacements" " (output=\"" + output + "\")"); } CraftDefinition *def = new CraftDefinitionShaped( output, width, recipe, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionShapeless */ else if(type == "shapeless"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (shapeless)" + if (output.empty()) + throw LuaError("Crafting definition (shapeless)" " is missing an output"); std::vector recipe; lua_getfield(L, table, "recipe"); if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition (shapeless)" + throw LuaError("Crafting definition (shapeless)" " is missing a recipe" " (output=\"" + output + "\")"); if(!readCraftRecipeShapeless(L, -1, recipe)) - throw LuaError(L, "Invalid crafting recipe" + throw LuaError("Invalid crafting recipe" " (output=\"" + output + "\")"); CraftReplacements replacements; @@ -199,13 +197,13 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError("Invalid replacements" " (output=\"" + output + "\")"); } CraftDefinition *def = new CraftDefinitionShapeless( output, recipe, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionToolRepair @@ -216,20 +214,20 @@ int ModApiCraft::l_register_craft(lua_State *L) CraftDefinition *def = new CraftDefinitionToolRepair( additional_wear); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionCooking */ else if(type == "cooking"){ std::string output = getstringfield_default(L, table, "output", ""); - if(output == "") - throw LuaError(L, "Crafting definition (cooking)" + if (output.empty()) + throw LuaError("Crafting definition (cooking)" " is missing an output"); std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (cooking)" + if (recipe.empty()) + throw LuaError("Crafting definition (cooking)" " is missing a recipe" " (output=\"" + output + "\")"); @@ -240,21 +238,21 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError("Invalid replacements" " (cooking output=\"" + output + "\")"); } CraftDefinition *def = new CraftDefinitionCooking( output, recipe, cooktime, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionFuel */ else if(type == "fuel"){ std::string recipe = getstringfield_default(L, table, "recipe", ""); - if(recipe == "") - throw LuaError(L, "Crafting definition (fuel)" + if (recipe.empty()) + throw LuaError("Crafting definition (fuel)" " is missing a recipe"); float burntime = getfloatfield_default(L, table, "burntime", 1.0); @@ -264,23 +262,111 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError("Invalid replacements" " (fuel recipe=\"" + recipe + "\")"); } CraftDefinition *def = new CraftDefinitionFuel( recipe, burntime, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } else { - throw LuaError(L, "Unknown crafting definition type: \"" + type + "\""); + throw LuaError("Unknown crafting definition type: \"" + type + "\""); } lua_pop(L, 1); 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) { @@ -303,18 +389,23 @@ int ModApiCraft::l_get_craft_result(lua_State *L) ICraftDefManager *cdef = gdef->cdef(); CraftInput input(method, width, items); CraftOutput output; - bool got = cdef->getCraftResult(input, output, true, gdef); + std::vector output_replacements; + bool got = cdef->getCraftResult(input, output, output_replacements, true, gdef); lua_newtable(L); // output table - if(got){ + if (got) { ItemStack item; item.deSerialize(output.item, gdef->idef()); LuaItemStack::create(L, item); lua_setfield(L, -2, "item"); setintfield(L, -1, "time", output.time); + push_items(L, output_replacements); + lua_setfield(L, -2, "replacements"); } else { LuaItemStack::create(L, ItemStack()); lua_setfield(L, -2, "item"); setintfield(L, -1, "time", 0); + lua_newtable(L); + lua_setfield(L, -2, "replacements"); } lua_newtable(L); // decremented input table lua_pushstring(L, method_s.c_str()); @@ -326,56 +417,90 @@ int ModApiCraft::l_get_craft_result(lua_State *L) return 2; } + +static void push_craft_recipe(lua_State *L, IGameDef *gdef, + const CraftDefinition *recipe, + const CraftOutput &tmpout) +{ + CraftInput input = recipe->getInput(tmpout, gdef); + CraftOutput output = recipe->getOutput(input, gdef); + + lua_newtable(L); // items + std::vector::const_iterator iter = input.items.begin(); + for (u16 j = 1; iter != input.items.end(); ++iter, j++) { + if (iter->empty()) + continue; + lua_pushstring(L, iter->name.c_str()); + lua_rawseti(L, -2, j); + } + lua_setfield(L, -2, "items"); + setintfield(L, -1, "width", input.width); + + std::string method_s; + switch (input.method) { + case CRAFT_METHOD_NORMAL: + method_s = "normal"; + break; + case CRAFT_METHOD_COOKING: + method_s = "cooking"; + break; + case CRAFT_METHOD_FUEL: + method_s = "fuel"; + break; + default: + 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"); +} + +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; + } + + std::vector::const_iterator it = recipes.begin(); + for (unsigned i = 0; it != recipes.end(); ++it) { + lua_newtable(L); + push_craft_recipe(L, gdef, *it, output); + lua_rawseti(L, -2, ++i); + } +} + + // get_craft_recipe(result item) int ModApiCraft::l_get_craft_recipe(lua_State *L) { NO_MAP_LOCK_REQUIRED; - int k = 1; - int input_i = 1; - std::string o_item = luaL_checkstring(L,input_i); + std::string item = luaL_checkstring(L, 1); + Server *server = getServer(L); + CraftOutput output(item, 0); + std::vector recipes = server->cdef() + ->getCraftRecipes(output, server, 1); - IGameDef *gdef = getServer(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::const_iterator - i = input.items.begin(); - i != input.items.end(); i++, k++) - { - if (i->empty()) - { - continue; - } - lua_pushinteger(L,k); - 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,"normal"); - 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_createtable(L, 1, 0); + + if (recipes.empty()) { lua_pushnil(L); lua_setfield(L, -2, "items"); setintfield(L, -1, "width", 0); + return 1; } + push_craft_recipe(L, server, recipes[0], output); return 1; } @@ -384,59 +509,13 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L) { NO_MAP_LOCK_REQUIRED; - std::string o_item = luaL_checkstring(L,1); - IGameDef *gdef = getServer(L); - ICraftDefManager *cdef = gdef->cdef(); - CraftInput input; - CraftOutput output(o_item,0); - std::vector recipes_list; - recipes_list = cdef->getCraftRecipes(output, gdef); - if (recipes_list.empty()) { - lua_pushnil(L); - return 1; - } + std::string item = luaL_checkstring(L, 1); + Server *server = getServer(L); + CraftOutput output(item, 0); + std::vector recipes = server->cdef() + ->getCraftRecipes(output, server); - lua_createtable(L, recipes_list.size(), 0); - std::vector::const_iterator iter = recipes_list.begin(); - for (u16 i = 0; iter != recipes_list.end(); iter++) { - CraftOutput tmpout; - tmpout.item = ""; - tmpout.time = 0; - tmpout = (*iter)->getOutput(input, gdef); - std::string query = tmpout.item; - char *fmtpos, *fmt = &query[0]; - if (strtok_r(fmt, " ", &fmtpos) == output.item) { - input = (*iter)->getInput(output, gdef); - lua_newtable(L); - lua_newtable(L); // items - std::vector::const_iterator iter = input.items.begin(); - for (u16 j = 1; iter != input.items.end(); iter++, j++) { - if (iter->empty()) - continue; - lua_pushstring(L, iter->name.c_str()); - lua_rawseti(L, -2, j); - } - lua_setfield(L, -2, "items"); - setintfield(L, -1, "width", input.width); - switch (input.method) { - case CRAFT_METHOD_NORMAL: - lua_pushstring(L, "normal"); - 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"); - lua_pushstring(L, &tmpout.item[0]); - lua_setfield(L, -2, "output"); - lua_rawseti(L, -2, ++i); - } - } + push_craft_recipes(L, server, recipes, output); return 1; } @@ -446,4 +525,5 @@ 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); }