241 changes: 15 additions & 226 deletions src/script/lua_api/l_craft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,248 +42,37 @@ struct EnumString ModApiCraft::es_CraftMethod[] =
{0, NULL},
};


// helper for register_craft
bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index,
int &width, std::vector<std::string> &recipe)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;

if(!lua_istable(L, index))
return false;

lua_pushnil(L);
int rowcount = 0;
while(lua_next(L, index) != 0){
int colcount = 0;
// key at index -2 and value at index -1
if(!lua_istable(L, -1))
return false;
int table2 = lua_gettop(L);
lua_pushnil(L);
while(lua_next(L, table2) != 0){
// key at index -2 and value at index -1
if(!lua_isstring(L, -1))
return false;
recipe.push_back(lua_tostring(L, -1));
// removes value, keeps key for next iteration
lua_pop(L, 1);
colcount++;
}
if(rowcount == 0){
width = colcount;
} else {
if(colcount != width)
return false;
}
// removes value, keeps key for next iteration
lua_pop(L, 1);
rowcount++;
}
return width != 0;
}

// helper for register_craft
bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index,
std::vector<std::string> &recipe)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;

if(!lua_istable(L, index))
return false;

lua_pushnil(L);
while(lua_next(L, index) != 0){
// key at index -2 and value at index -1
if(!lua_isstring(L, -1))
return false;
recipe.push_back(lua_tostring(L, -1));
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
return true;
}

// helper for register_craft
bool ModApiCraft::readCraftReplacements(lua_State *L, int index,
CraftReplacements &replacements)
{
if(index < 0)
index = lua_gettop(L) + 1 + index;

if(!lua_istable(L, index))
return false;

lua_pushnil(L);
while(lua_next(L, index) != 0){
// key at index -2 and value at index -1
if(!lua_istable(L, -1))
return false;
lua_rawgeti(L, -1, 1);
if(!lua_isstring(L, -1))
return false;
std::string replace_from = lua_tostring(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);
lua_pop(L, 1);
replacements.pairs.push_back(
std::make_pair(replace_from, replace_to));
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
return true;
}
// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
int ModApiCraft::l_register_craft(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
//infostream<<"register_craft"<<std::endl;
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 type = getstringfield_default(L, table, "type", "shaped");

/*
CraftDefinitionShaped
*/
if(type == "shaped"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(L, "Crafting definition is missing an output");

int width = 0;
std::vector<std::string> recipe;
lua_getfield(L, table, "recipe");
if(lua_isnil(L, -1))
throw LuaError(L, "Crafting definition is missing a recipe"
" (output=\"" + output + "\")");
if(!readCraftRecipeShaped(L, -1, width, recipe))
throw LuaError(L, "Invalid crafting recipe"
" (output=\"" + output + "\")");

CraftReplacements replacements;
lua_getfield(L, table, "replacements");
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(L, "Invalid replacements"
" (output=\"" + output + "\")");
}

CraftDefinition *def = new CraftDefinitionShaped(
output, width, recipe, replacements);
craftdef->registerCraft(def);
}
/*
CraftDefinitionShapeless
*/
else if(type == "shapeless"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(L, "Crafting definition (shapeless)"
" is missing an output");

std::vector<std::string> recipe;
lua_getfield(L, table, "recipe");
if(lua_isnil(L, -1))
throw LuaError(L, "Crafting definition (shapeless)"
" is missing a recipe"
" (output=\"" + output + "\")");
if(!readCraftRecipeShapeless(L, -1, recipe))
throw LuaError(L, "Invalid crafting recipe"
" (output=\"" + output + "\")");

CraftReplacements replacements;
lua_getfield(L, table, "replacements");
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(L, "Invalid replacements"
" (output=\"" + output + "\")");
}
CraftDefinition* def = read_craft(L,1);

CraftDefinition *def = new CraftDefinitionShapeless(
output, recipe, replacements);
if (def != 0)
craftdef->registerCraft(def);
}
/*
CraftDefinitionToolRepair
*/
else if(type == "toolrepair"){
float additional_wear = getfloatfield_default(L, table,
"additional_wear", 0.0);

CraftDefinition *def = new CraftDefinitionToolRepair(
additional_wear);
craftdef->registerCraft(def);
}
/*
CraftDefinitionCooking
*/
else if(type == "cooking"){
std::string output = getstringfield_default(L, table, "output", "");
if(output == "")
throw LuaError(L, "Crafting definition (cooking)"
" is missing an output");

std::string recipe = getstringfield_default(L, table, "recipe", "");
if(recipe == "")
throw LuaError(L, "Crafting definition (cooking)"
" is missing a recipe"
" (output=\"" + output + "\")");

float cooktime = getfloatfield_default(L, table, "cooktime", 3.0);

CraftReplacements replacements;
lua_getfield(L, table, "replacements");
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(L, "Invalid replacements"
" (cooking output=\"" + output + "\")");
}

CraftDefinition *def = new CraftDefinitionCooking(
output, recipe, cooktime, replacements);
craftdef->registerCraft(def);
}
/*
CraftDefinitionFuel
*/
else if(type == "fuel"){
std::string recipe = getstringfield_default(L, table, "recipe", "");
if(recipe == "")
throw LuaError(L, "Crafting definition (fuel)"
" is missing a recipe");
lua_pop(L, 1);
return 0; /* number of results */
}

float burntime = getfloatfield_default(L, table, "burntime", 1.0);
// remove_craft({output=item, recipe={{item00,item10},{item01,item11}})
int ModApiCraft::l_remove_craft(lua_State *L)
{
// Get the writable craft definition manager from the server
IWritableCraftDefManager *craftdef =
getServer(L)->getWritableCraftDefManager();

CraftReplacements replacements;
lua_getfield(L, table, "replacements");
if(!lua_isnil(L, -1))
{
if(!readCraftReplacements(L, -1, replacements))
throw LuaError(L, "Invalid replacements"
" (fuel recipe=\"" + recipe + "\")");
}
CraftDefinition* def = read_craft(L,1);

CraftDefinition *def = new CraftDefinitionFuel(
recipe, burntime, replacements);
craftdef->registerCraft(def);
}
else
{
throw LuaError(L, "Unknown crafting definition type: \"" + type + "\"");
}
if (def != 0)
craftdef->removeCraft(def);

lua_pop(L, 1);
return 0; /* number of results */
Expand Down
8 changes: 1 addition & 7 deletions src/script/lua_api/l_craft.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@ class ModApiCraft : public ModApiBase {
bool Initialize(lua_State* L, int top);
private:
static int l_register_craft(lua_State *L);
static int l_remove_craft(lua_State *L);
static int l_get_craft_recipe(lua_State *L);
static int l_get_all_craft_recipes(lua_State *L);
static int l_get_craft_result(lua_State *L);

static bool readCraftReplacements(lua_State *L, int index,
CraftReplacements &replacements);
static bool readCraftRecipeShapeless(lua_State *L, int index,
std::vector<std::string> &recipe);
static bool readCraftRecipeShaped(lua_State *L, int index,
int &width, std::vector<std::string> &recipe);

static struct EnumString es_CraftMethod[];
};

Expand Down