}
};
+class ModNameStorer
+{
+private:
+ lua_State *L;
+public:
+ ModNameStorer(lua_State *L_, const std::string modname):
+ L(L_)
+ {
+ // Store current modname in registry
+ lua_pushstring(L, modname.c_str());
+ lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+ }
+ ~ModNameStorer()
+ {
+ // Clear current modname in registry
+ lua_pushnil(L);
+ lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+ }
+};
+
+std::string get_current_modname(lua_State *L)
+{
+ lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname");
+ std::string modname = "";
+ if(lua_type(L, -1) == LUA_TSTRING)
+ modname = lua_tostring(L, -1);
+ lua_pop(L, 1);
+ return modname;
+}
+
+void check_modname_prefix(lua_State *L, std::string &name)
+{
+ if(name.size() == 0)
+ throw LuaError(L, std::string("Name is empty"));
+
+ if(name[0] == ':'){
+ name = name.substr(1);
+ return;
+ }
+
+ std::string modname = get_current_modname(L);
+ assert(modname != "");
+
+ // For __builtin, anything goes
+ if(modname == "__builtin")
+ return;
+
+ if(name.substr(0, modname.size()+1) != modname + "_")
+ throw LuaError(L, std::string("Name \"")+name
+ +"\" does not follow naming conventions: "
+ +"\"modname_\" or \":\" prefix required)");
+}
+
static v3f readFloatPos(lua_State *L, int index)
{
v3f pos;
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)
+ 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);
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
- InventoryList *invlist = inv->addList(name, items.size());
+ 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 != "")
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_pushvalue(L, table_insert);
lua_pushvalue(L, table);
if(item == NULL){
- lua_pushnil(L);
+ lua_pushstring(L, "");
} else {
lua_pushstring(L, item->getItemString().c_str());
}
if(lua_pcall(L, 2, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ 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
*/
// register_entity(name, prototype)
static int l_register_entity(lua_State *L)
{
- const char *name = luaL_checkstring(L, 1);
- infostream<<"register_entity: "<<name<<std::endl;
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_entity: "<<name<<std::endl;
luaL_checktype(L, 2, LUA_TTABLE);
// Get minetest.registered_entities
int registered_entities = lua_gettop(L);
lua_pushvalue(L, 2); // Object = param 2 -> stack top
// registered_entities[name] = object
- lua_setfield(L, registered_entities, name);
+ lua_setfield(L, registered_entities, name.c_str());
// Get registered object to top of stack
lua_pushvalue(L, 2);
lua_pushnumber(L, active_object_count);
lua_pushnumber(L, active_object_count_wider);
if(lua_pcall(L, 4, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
}
};
// register_abm({...})
static int l_register_abm(lua_State *L)
{
- infostream<<"register_abm"<<std::endl;
+ //infostream<<"register_abm"<<std::endl;
luaL_checktype(L, 1, LUA_TTABLE);
// Get minetest.registered_abms
// register_tool(name, {lots of stuff})
static int l_register_tool(lua_State *L)
{
- const char *name = luaL_checkstring(L, 1);
- infostream<<"register_tool: "<<name<<std::endl;
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_tool: "<<name<<std::endl;
luaL_checktype(L, 2, LUA_TTABLE);
int table = 2;
IWritableToolDefManager *tooldef =
server->getWritableToolDefManager();
- ToolDefinition def;
-
- getstringfield(L, table, "image", def.imagename);
- getfloatfield(L, table, "basetime", def.properties.basetime);
- getfloatfield(L, table, "dt_weight", def.properties.dt_weight);
- getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness);
- getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness);
- getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability);
- getfloatfield(L, table, "basedurability", def.properties.basedurability);
- getfloatfield(L, table, "dd_weight", def.properties.dd_weight);
- getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness);
- getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness);
- getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability);
+ ToolDefinition def = read_tool_definition(L, table);
tooldef->registerTool(name, def);
return 0; /* number of results */
// register_craftitem(name, {lots of stuff})
static int l_register_craftitem(lua_State *L)
{
- const char *name = luaL_checkstring(L, 1);
- infostream<<"register_craftitem: "<<name<<std::endl;
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_craftitem: "<<name<<std::endl;
luaL_checktype(L, 2, LUA_TTABLE);
int table = 2;
craftitemdef->registerCraftItem(name, def);
lua_pushvalue(L, table);
- scriptapi_add_craftitem(L, name);
+ scriptapi_add_craftitem(L, name.c_str());
return 0; /* number of results */
}
// register_node(name, {lots of stuff})
static int l_register_node(lua_State *L)
{
- const char *name = luaL_checkstring(L, 1);
- infostream<<"register_node: "<<name<<std::endl;
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_node: "<<name<<std::endl;
luaL_checktype(L, 2, LUA_TTABLE);
int nodedef_table = 2;
lua_getglobal(L, "minetest");
lua_getfield(L, -1, "registered_nodes");
luaL_checktype(L, -1, LUA_TTABLE);
- lua_pushstring(L, name);
+ lua_pushstring(L, name.c_str());
lua_pushvalue(L, nodedef_table);
lua_settable(L, -3);
// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
static int l_register_craft(lua_State *L)
{
- infostream<<"register_craft"<<std::endl;
+ //infostream<<"register_craft"<<std::endl;
luaL_checktype(L, 1, LUA_TTABLE);
int table0 = 1;
width = colcount;
} else {
if(colcount != width){
- script_error(L, "error: %s\n", "Invalid crafting recipe");
+ std::string error;
+ error += "Invalid crafting recipe (output=\""
+ + output + "\")";
+ throw LuaError(L, error);
}
}
// removes value, keeps key for next iteration
return 0;
}
- // get_wielded_itemstring(self)
- static int l_get_wielded_itemstring(lua_State *L)
+ // get_wield_digging_properties(self)
+ static int l_get_wield_digging_properties(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0;
// Do it
- InventoryItem *item = co->getWieldedItem();
- if(item == NULL){
- lua_pushnil(L);
- return 1;
- }
- lua_pushstring(L, item->getItemString().c_str());
- return 1;
- }
-
- // get_wielded_item(self)
- static int l_get_wielded_item(lua_State *L)
- {
- ObjectRef *ref = checkobject(L, 1);
- ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
- // Do it
- InventoryItem *item0 = co->getWieldedItem();
- if(item0 == NULL){
- lua_pushnil(L);
- return 1;
- }
- if(std::string("MaterialItem") == item0->getName()){
- MaterialItem *item = (MaterialItem*)item0;
- lua_newtable(L);
- lua_pushstring(L, "NodeItem");
- lua_setfield(L, -2, "type");
- lua_pushstring(L, item->getNodeName().c_str());
- lua_setfield(L, -2, "name");
- }
- else if(std::string("CraftItem") == item0->getName()){
- CraftItem *item = (CraftItem*)item0;
- lua_newtable(L);
- lua_pushstring(L, "CraftItem");
- lua_setfield(L, -2, "type");
- lua_pushstring(L, item->getSubName().c_str());
- lua_setfield(L, -2, "name");
- }
- else if(std::string("ToolItem") == item0->getName()){
- ToolItem *item = (ToolItem*)item0;
- lua_newtable(L);
- lua_pushstring(L, "ToolItem");
- lua_setfield(L, -2, "type");
- lua_pushstring(L, item->getToolName().c_str());
- lua_setfield(L, -2, "name");
- lua_pushstring(L, itos(item->getWear()).c_str());
- lua_setfield(L, -2, "wear");
- }
- else{
- errorstream<<"l_get_wielded_item: Unknown item name: \""
- <<item0->getName()<<"\""<<std::endl;
- lua_pushnil(L);
- }
+ ToolDiggingProperties prop;
+ co->getWieldDiggingProperties(&prop);
+ push_tool_digging_properties(L, prop);
return 1;
}
// Return
lua_pushboolean(L, added);
if(!added)
- lua_pushstring(L, "does not fit");
+ lua_pushstring(L, "failed to add item");
return 2;
} catch(SerializationError &e){
// Return
const char *name = lua_tostring(L, 2);
// Do it
inventory_set_list_from_lua(&player->inventory, name, L, 3,
- player->getEnv()->getGameDef());
+ player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
player->m_inventory_not_sent = true;
return 0;
}
return 1;
}
+ // get_wielded_itemstring(self)
+ static int l_get_wielded_itemstring(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerRemotePlayer *player = getplayer(ref);
+ if(player == NULL) return 0;
+ // Do it
+ InventoryItem *item = player->getWieldedItem();
+ if(item == NULL){
+ lua_pushnil(L);
+ return 1;
+ }
+ lua_pushstring(L, item->getItemString().c_str());
+ return 1;
+ }
+
+ // get_wielded_item(self)
+ static int l_get_wielded_item(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ ServerRemotePlayer *player = getplayer(ref);
+ if(player == NULL) return 0;
+ // Do it
+ InventoryItem *item0 = player->getWieldedItem();
+ if(item0 == NULL){
+ lua_pushnil(L);
+ return 1;
+ }
+ if(std::string("MaterialItem") == item0->getName()){
+ MaterialItem *item = (MaterialItem*)item0;
+ lua_newtable(L);
+ lua_pushstring(L, "NodeItem");
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, item->getNodeName().c_str());
+ lua_setfield(L, -2, "name");
+ }
+ else if(std::string("CraftItem") == item0->getName()){
+ CraftItem *item = (CraftItem*)item0;
+ lua_newtable(L);
+ lua_pushstring(L, "CraftItem");
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, item->getSubName().c_str());
+ lua_setfield(L, -2, "name");
+ }
+ else if(std::string("ToolItem") == item0->getName()){
+ ToolItem *item = (ToolItem*)item0;
+ lua_newtable(L);
+ lua_pushstring(L, "ToolItem");
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, item->getToolName().c_str());
+ lua_setfield(L, -2, "name");
+ lua_pushstring(L, itos(item->getWear()).c_str());
+ lua_setfield(L, -2, "wear");
+ }
+ else{
+ errorstream<<"l_get_wielded_item: Unknown item name: \""
+ <<item0->getName()<<"\""<<std::endl;
+ lua_pushnil(L);
+ }
+ return 1;
+ }
+
public:
ObjectRef(ServerActiveObject *object):
m_object(object)
method(ObjectRef, moveto),
method(ObjectRef, punch),
method(ObjectRef, right_click),
- method(ObjectRef, get_wielded_itemstring),
- method(ObjectRef, get_wielded_item),
+ method(ObjectRef, get_wield_digging_properties),
method(ObjectRef, damage_wielded_item),
method(ObjectRef, add_to_inventory),
method(ObjectRef, add_to_inventory_later),
method(ObjectRef, get_player_name),
method(ObjectRef, inventory_set_list),
method(ObjectRef, inventory_get_list),
+ method(ObjectRef, get_wielded_itemstring),
+ method(ObjectRef, get_wielded_item),
{0,0}
};
ObjectRef::Register(L);
}
+bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
+ const std::string &modname)
+{
+ ModNameStorer modnamestorer(L, modname);
+
+ bool success = false;
+
+ try{
+ success = script_load(L, scriptpath.c_str());
+ }
+ catch(LuaError &e){
+ errorstream<<"Error loading mod \""<<modname
+ <<"\": "<<e.what()<<std::endl;
+ }
+
+ return success;
+}
+
void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
{
realitycheck(L);
lua_pushvalue(L, -2); // Get previous stack top as first parameter
lua_pushstring(L, name);
if(lua_pcall(L, 2, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
}
#endif
lua_pushstring(L, name.c_str());
lua_pushstring(L, message.c_str());
if(lua_pcall(L, 2, 1, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
bool ate = lua_toboolean(L, -1);
lua_pop(L, 1);
if(ate)
// Call function
objectref_get_or_create(L, player);
if(lua_pcall(L, 1, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
// Call function
objectref_get_or_create(L, player);
if(lua_pcall(L, 1, 1, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
bool positioning_handled = lua_toboolean(L, -1);
lua_pop(L, 1);
if(positioning_handled)
return positioning_handled_by_some;
}
+void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
+{
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "creative_inventory");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ inventory_set_list_from_lua(&player->inventory, "main", L, -1,
+ player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE);
+}
+
/*
craftitem
*/
objectref_get_or_create(L, dropper);
pushFloatPos(L, pos);
if(lua_pcall(L, 3, 1, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
result = lua_toboolean(L, -1);
}
return result;
objectref_get_or_create(L, placer);
pushFloatPos(L, pos);
if(lua_pcall(L, 3, 1, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
result = lua_toboolean(L, -1);
}
return result;
objectref_get_or_create(L, user);
pushPointedThing(L, pointed);
if(lua_pcall(L, 3, 1, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
result = lua_toboolean(L, -1);
}
return result;
// Call function
lua_pushnumber(L, dtime);
if(lua_pcall(L, 1, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
pushnode(L, newnode, ndef);
objectref_get_or_create(L, placer);
if(lua_pcall(L, 3, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
pushnode(L, oldnode, ndef);
objectref_get_or_create(L, digger);
if(lua_pcall(L, 3, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
pushnode(L, node, ndef);
objectref_get_or_create(L, puncher);
if(lua_pcall(L, 3, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
pushpos(L, minp);
pushpos(L, maxp);
if(lua_pcall(L, 2, 0, 0))
- script_error(L, "error: %s\n", lua_tostring(L, -1));
+ script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration
}
}
script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1));
}
-// Calls entity:on_punch(ObjectRef puncher)
+// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch)
void scriptapi_luaentity_punch(lua_State *L, u16 id,
- ServerActiveObject *puncher)
+ ServerActiveObject *puncher, float time_from_last_punch)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
objectref_get_or_create(L, puncher); // Clicker reference
+ lua_pushnumber(L, time_from_last_punch);
// Call with 2 arguments, 0 results
- if(lua_pcall(L, 2, 0, 0))
+ if(lua_pcall(L, 3, 0, 0))
script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
}