X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Flua_api%2Fl_craft.cpp;h=2236566de1caabac46fb0886a2ae6976a9ab6bed;hb=46276414ed51d61dc29879ac85e861dc770d90da;hp=c5732bad2e1b0f2d966eefd4f18d8215205f3680;hpb=371b39a09a0bf248d674fae718f5ff369e895b66;p=dragonfireclient.git diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index c5732bad2..2236566de 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) @@ -150,16 +149,16 @@ 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"); + 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,13 +166,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 CraftDefinitionShaped( output, width, recipe, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionShapeless @@ -181,17 +180,17 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "shapeless"){ std::string output = getstringfield_default(L, table, "output", ""); if(output == "") - throw LuaError(L, "Crafting definition (shapeless)" + 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 +198,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,7 +215,7 @@ int ModApiCraft::l_register_craft(lua_State *L) CraftDefinition *def = new CraftDefinitionToolRepair( additional_wear); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionCooking @@ -224,12 +223,12 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "cooking"){ std::string output = getstringfield_default(L, table, "output", ""); if(output == "") - throw LuaError(L, "Crafting definition (cooking)" + 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)" + throw LuaError("Crafting definition (cooking)" " is missing a recipe" " (output=\"" + output + "\")"); @@ -240,13 +239,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" " (cooking output=\"" + output + "\")"); } CraftDefinition *def = new CraftDefinitionCooking( output, recipe, cooktime, replacements); - craftdef->registerCraft(def); + craftdef->registerCraft(def, getServer(L)); } /* CraftDefinitionFuel @@ -254,7 +253,7 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "fuel"){ std::string recipe = getstringfield_default(L, table, "recipe", ""); if(recipe == "") - throw LuaError(L, "Crafting definition (fuel)" + throw LuaError("Crafting definition (fuel)" " is missing a recipe"); float burntime = getfloatfield_default(L, table, "burntime", 1.0); @@ -264,23 +263,97 @@ 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 != "") { + if (craftdef->clearCraftRecipesByOutput(c_output, getServer(L))) + return 0; + else + throw LuaError("No craft recipe known for output" + " (output=\"" + output + "\")"); + } + 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 == "") + 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 == "") + throw LuaError("Crafting definition (fuel)" + " is missing a recipe"); + recipe.push_back(rec); + } else { + throw LuaError("Unknown crafting definition type: \"" + type + "\""); + } + if (!craftdef->clearCraftRecipesByInput(method, width, recipe, getServer(L))) + throw LuaError("No crafting specified for input"); + lua_pop(L, 1); + return 0; +} + // get_craft_result(input) int ModApiCraft::l_get_craft_result(lua_State *L) { @@ -303,18 +376,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 +404,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,74 +496,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 = cdef->getCraftRecipes(output, gdef); - if (recipes_list.empty()) - { - lua_pushnil(L); - return 1; - } - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - lua_newtable(L); - int table = lua_gettop(L); - for (std::vector::const_iterator - i = recipes_list.begin(); - i != recipes_list.end(); i++) - { - CraftOutput tmpout; - tmpout.item = ""; - tmpout.time = 0; - CraftDefinition *def = *i; - tmpout = def->getOutput(input, gdef); - std::string query = tmpout.item; - char *fmtpos, *fmt = &query[0]; - if (strtok_r(fmt, " ", &fmtpos) == output.item) - { - input = def->getInput(output, gdef); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - lua_newtable(L); - int k = 1; - 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"); - lua_pushstring(L, &tmpout.item[0]); - lua_setfield(L, -2, "output"); - if (lua_pcall(L, 2, 0, 0)) - script_error(L); - } - } + std::string item = luaL_checkstring(L, 1); + Server *server = getServer(L); + CraftOutput output(item, 0); + std::vector recipes = server->cdef() + ->getCraftRecipes(output, server); + + push_craft_recipes(L, server, recipes, output); return 1; } @@ -461,4 +512,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); }