+static video::SColor readARGB8(lua_State *L, int index)
+{
+ video::SColor color;
+ luaL_checktype(L, index, LUA_TTABLE);
+ lua_getfield(L, index, "a");
+ if(lua_isnumber(L, -1))
+ color.setAlpha(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ lua_getfield(L, index, "r");
+ color.setRed(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ lua_getfield(L, index, "g");
+ color.setGreen(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ lua_getfield(L, index, "b");
+ color.setBlue(lua_tonumber(L, -1));
+ lua_pop(L, 1);
+ return color;
+}
+
+static core::aabbox3d<f32> read_aabbox3df32(lua_State *L, int index, f32 scale)
+{
+ core::aabbox3d<f32> box;
+ if(lua_istable(L, -1)){
+ lua_rawgeti(L, -1, 1);
+ box.MinEdge.X = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ lua_rawgeti(L, -1, 2);
+ box.MinEdge.Y = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ lua_rawgeti(L, -1, 3);
+ box.MinEdge.Z = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ lua_rawgeti(L, -1, 4);
+ box.MaxEdge.X = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ lua_rawgeti(L, -1, 5);
+ box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ lua_rawgeti(L, -1, 6);
+ box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
+ lua_pop(L, 1);
+ }
+ return box;
+}
+
+static v2s16 read_v2s16(lua_State *L, int index)
+{
+ v2s16 p;
+ luaL_checktype(L, index, LUA_TTABLE);
+ lua_getfield(L, index, "x");
+ p.X = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, index, "y");
+ p.Y = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ return p;
+}
+
+static v2f read_v2f(lua_State *L, int index)
+{
+ v2f p;
+ luaL_checktype(L, index, LUA_TTABLE);
+ lua_getfield(L, index, "x");
+ p.X = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, index, "y");
+ p.Y = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ return p;
+}
+
+static bool getstringfield(lua_State *L, int table,
+ const char *fieldname, std::string &result)
+{
+ lua_getfield(L, table, fieldname);
+ bool got = false;
+ if(lua_isstring(L, -1)){
+ result = lua_tostring(L, -1);
+ got = true;
+ }
+ lua_pop(L, 1);
+ return got;
+}
+
+static bool getintfield(lua_State *L, int table,
+ const char *fieldname, int &result)
+{
+ lua_getfield(L, table, fieldname);
+ bool got = false;
+ if(lua_isnumber(L, -1)){
+ result = lua_tonumber(L, -1);
+ got = true;
+ }
+ lua_pop(L, 1);
+ return got;
+}
+
+static bool getfloatfield(lua_State *L, int table,
+ const char *fieldname, float &result)
+{
+ lua_getfield(L, table, fieldname);
+ bool got = false;
+ if(lua_isnumber(L, -1)){
+ result = lua_tonumber(L, -1);
+ got = true;
+ }
+ lua_pop(L, 1);
+ return got;
+}
+
+static bool getboolfield(lua_State *L, int table,
+ const char *fieldname, bool &result)
+{
+ lua_getfield(L, table, fieldname);
+ bool got = false;
+ if(lua_isboolean(L, -1)){
+ result = lua_toboolean(L, -1);
+ got = true;
+ }
+ lua_pop(L, 1);
+ return got;
+}
+
+static std::string getstringfield_default(lua_State *L, int table,
+ const char *fieldname, const std::string &default_)
+{
+ std::string result = default_;
+ getstringfield(L, table, fieldname, result);
+ return result;
+}
+
+static int getintfield_default(lua_State *L, int table,
+ const char *fieldname, int default_)
+{
+ int result = default_;
+ getintfield(L, table, fieldname, result);
+ return result;
+}
+
+/*static float getfloatfield_default(lua_State *L, int table,
+ const char *fieldname, float default_)
+{
+ float result = default_;
+ getfloatfield(L, table, fieldname, result);
+ return result;
+}*/
+
+static bool getboolfield_default(lua_State *L, int table,
+ const char *fieldname, bool default_)
+{
+ bool result = default_;
+ getboolfield(L, table, fieldname, result);
+ return result;
+}
+
+struct EnumString
+{
+ int num;
+ const char *str;
+};
+
+static bool string_to_enum(const EnumString *spec, int &result,
+ const std::string &str)
+{
+ const EnumString *esp = spec;
+ while(esp->str){
+ if(str == std::string(esp->str)){
+ result = esp->num;
+ return true;
+ }
+ esp++;
+ }
+ return false;
+}
+
+/*static bool enum_to_string(const EnumString *spec, std::string &result,
+ int num)
+{
+ const EnumString *esp = spec;
+ while(esp){
+ if(num == esp->num){
+ result = esp->str;
+ return true;
+ }
+ esp++;
+ }
+ return false;
+}*/
+
+static int getenumfield(lua_State *L, int table,
+ const char *fieldname, const EnumString *spec, int default_)
+{
+ int result = default_;
+ string_to_enum(spec, result,
+ getstringfield_default(L, table, fieldname, ""));
+ return result;
+}
+
+static void setfloatfield(lua_State *L, int table,
+ const char *fieldname, float value)
+{
+ lua_pushnumber(L, value);
+ if(table < 0)
+ table -= 1;
+ lua_setfield(L, table, fieldname);
+}
+
+/*
+ Inventory stuff
+*/
+
+static void inventory_set_list_from_lua(Inventory *inv, const char *name,
+ lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1)
+{
+ if(tableindex < 0)
+ tableindex = lua_gettop(L) + 1 + tableindex;
+ // If nil, delete list
+ if(lua_isnil(L, tableindex)){
+ inv->deleteList(name);
+ return;
+ }
+ // Otherwise set list
+ std::list<std::string> items;
+ luaL_checktype(L, tableindex, LUA_TTABLE);
+ int table = tableindex;
+ lua_pushnil(L);
+ while(lua_next(L, table) != 0){
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ std::string itemstring = lua_tostring(L, -1);
+ items.push_back(itemstring);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ int listsize = (forcesize != -1) ? forcesize : items.size();
+ InventoryList *invlist = inv->addList(name, listsize);
+ int index = 0;
+ for(std::list<std::string>::const_iterator
+ i = items.begin(); i != items.end(); i++){
+ if(forcesize != -1 && index == forcesize)
+ break;
+ const std::string &itemstring = *i;
+ InventoryItem *newitem = NULL;
+ if(itemstring != "")
+ newitem = InventoryItem::deSerialize(itemstring,
+ gamedef);
+ InventoryItem *olditem = invlist->changeItem(index, newitem);
+ delete olditem;
+ index++;
+ }
+ while(forcesize != -1 && index < forcesize){
+ InventoryItem *olditem = invlist->changeItem(index, NULL);
+ delete olditem;
+ index++;
+ }
+}
+
+static void inventory_get_list_to_lua(Inventory *inv, const char *name,
+ lua_State *L)
+{
+ InventoryList *invlist = inv->getList(name);
+ if(invlist == NULL){
+ lua_pushnil(L);
+ return;
+ }
+ // Get the table insert function
+ lua_getglobal(L, "table");
+ lua_getfield(L, -1, "insert");
+ int table_insert = lua_gettop(L);
+ // Create and fill table
+ lua_newtable(L);
+ int table = lua_gettop(L);
+ for(u32 i=0; i<invlist->getSize(); i++){
+ InventoryItem *item = invlist->getItem(i);
+ lua_pushvalue(L, table_insert);
+ lua_pushvalue(L, table);
+ if(item == NULL){
+ lua_pushstring(L, "");
+ } else {
+ lua_pushstring(L, item->getItemString().c_str());
+ }
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+ }
+}
+
+/*
+ ToolDiggingProperties
+*/
+
+static ToolDiggingProperties read_tool_digging_properties(
+ lua_State *L, int table)
+{
+ ToolDiggingProperties prop;
+ getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
+ getfloatfield(L, table, "basetime", prop.basetime);
+ getfloatfield(L, table, "dt_weight", prop.dt_weight);
+ getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
+ getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
+ getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
+ getfloatfield(L, table, "basedurability", prop.basedurability);
+ getfloatfield(L, table, "dd_weight", prop.dd_weight);
+ getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
+ getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
+ getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
+ return prop;
+}
+
+static void set_tool_digging_properties(lua_State *L, int table,
+ const ToolDiggingProperties &prop)
+{
+ setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval);
+ setfloatfield(L, table, "basetime", prop.basetime);
+ setfloatfield(L, table, "dt_weight", prop.dt_weight);
+ setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness);
+ setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness);
+ setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability);
+ setfloatfield(L, table, "basedurability", prop.basedurability);
+ setfloatfield(L, table, "dd_weight", prop.dd_weight);
+ setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness);
+ setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness);
+ setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability);
+}
+
+static void push_tool_digging_properties(lua_State *L,
+ const ToolDiggingProperties &prop)
+{
+ lua_newtable(L);
+ set_tool_digging_properties(L, -1, prop);
+}
+
+/*
+ ToolDefinition
+*/
+
+static ToolDefinition read_tool_definition(lua_State *L, int table)
+{
+ ToolDefinition def;
+ getstringfield(L, table, "image", def.imagename);
+ def.properties = read_tool_digging_properties(L, table);
+ return def;
+}
+
+static void push_tool_definition(lua_State *L, const ToolDefinition &def)
+{
+ lua_newtable(L);
+ lua_pushstring(L, def.imagename.c_str());
+ lua_setfield(L, -2, "image");
+ set_tool_digging_properties(L, -1, def.properties);
+}
+
+/*
+ EnumString definitions
+*/
+
+struct EnumString es_DrawType[] =
+{
+ {NDT_NORMAL, "normal"},
+ {NDT_AIRLIKE, "airlike"},
+ {NDT_LIQUID, "liquid"},
+ {NDT_FLOWINGLIQUID, "flowingliquid"},
+ {NDT_GLASSLIKE, "glasslike"},
+ {NDT_ALLFACES, "allfaces"},
+ {NDT_ALLFACES_OPTIONAL, "allfaces_optional"},
+ {NDT_TORCHLIKE, "torchlike"},
+ {NDT_SIGNLIKE, "signlike"},
+ {NDT_PLANTLIKE, "plantlike"},
+ {NDT_FENCELIKE, "fencelike"},
+ {NDT_RAILLIKE, "raillike"},
+ {0, NULL},
+};
+
+struct EnumString es_ContentParamType[] =
+{
+ {CPT_NONE, "none"},
+ {CPT_LIGHT, "light"},
+ {CPT_MINERAL, "mineral"},
+ {CPT_FACEDIR_SIMPLE, "facedir_simple"},
+ {0, NULL},
+};
+
+struct EnumString es_LiquidType[] =
+{
+ {LIQUID_NONE, "none"},
+ {LIQUID_FLOWING, "flowing"},
+ {LIQUID_SOURCE, "source"},
+ {0, NULL},
+};
+
+struct EnumString es_NodeBoxType[] =
+{
+ {NODEBOX_REGULAR, "regular"},
+ {NODEBOX_FIXED, "fixed"},
+ {NODEBOX_WALLMOUNTED, "wallmounted"},
+ {0, NULL},
+};
+
+struct EnumString es_Diggability[] =
+{
+ {DIGGABLE_NOT, "not"},
+ {DIGGABLE_NORMAL, "normal"},
+ {DIGGABLE_CONSTANT, "constant"},
+ {0, NULL},
+};
+