X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscriptapi.cpp;h=1a50e1e34e1571854c11323e229a2f5066d1a07b;hb=1c15f53318d49ccd148ec42b0a4345c4a8cd06bf;hp=06cf38d1e370f2493f2abd5e23af8ba11f198648;hpb=103d4793f00b2dd592739f686e90370c2d8953a3;p=dragonfireclient.git diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 06cf38d1e..1a50e1e34 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -107,6 +107,103 @@ class StackUnroller } }; +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)"); + + std::string subname = name.substr(modname.size()+1); + if(!string_allowed(subname, "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")) + throw LuaError(L, std::string("Name \"")+name + +"\" does not follow naming conventions: " + +"\"contains unallowed characters"); +} + +static void push_v3f(lua_State *L, v3f p) +{ + lua_newtable(L); + lua_pushnumber(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, p.Y); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, p.Z); + lua_setfield(L, -2, "z"); +} + +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 v3f readFloatPos(lua_State *L, int index) { v3f pos; @@ -127,13 +224,7 @@ static v3f readFloatPos(lua_State *L, int index) static void pushFloatPos(lua_State *L, v3f p) { p /= BS; - lua_newtable(L); - lua_pushnumber(L, p.X); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); - lua_setfield(L, -2, "z"); + push_v3f(L, p); } static void pushpos(lua_State *L, v3s16 p) @@ -168,7 +259,7 @@ static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef) static MapNode readnode(lua_State *L, int index, INodeDefManager *ndef) { lua_getfield(L, index, "name"); - const char *name = lua_tostring(L, -1); + const char *name = luaL_checkstring(L, -1); lua_pop(L, 1); u8 param1; lua_getfield(L, index, "param1"); @@ -233,32 +324,6 @@ static core::aabbox3d read_aabbox3df32(lua_State *L, int index, f32 scale) 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) { @@ -386,6 +451,175 @@ static int getenumfield(lua_State *L, int table, 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); +} + +static void warn_if_field_exists(lua_State *L, int table, + const char *fieldname, const std::string &message) +{ + lua_getfield(L, table, fieldname); + if(!lua_isnil(L, -1)){ + infostream<deleteList(name); + return; + } + // Otherwise set list + std::list 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 = luaL_checkstring(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::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; igetSize(); 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"}, @@ -454,8 +688,9 @@ static int l_register_nodedef_defaults(lua_State *L) // register_entity(name, prototype) static int l_register_entity(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_entity: "< 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); @@ -491,15 +726,18 @@ class LuaABM : public ActiveBlockModifier int m_id; std::set m_trigger_contents; + std::set m_required_neighbors; float m_trigger_interval; u32 m_trigger_chance; public: LuaABM(lua_State *L, int id, const std::set &trigger_contents, + const std::set &required_neighbors, float trigger_interval, u32 trigger_chance): m_lua(L), m_id(id), m_trigger_contents(trigger_contents), + m_required_neighbors(required_neighbors), m_trigger_interval(trigger_interval), m_trigger_chance(trigger_chance) { @@ -508,6 +746,10 @@ class LuaABM : public ActiveBlockModifier { return m_trigger_contents; } + virtual std::set getRequiredNeighbors() + { + return m_required_neighbors; + } virtual float getTriggerInterval() { return m_trigger_interval; @@ -546,14 +788,14 @@ class LuaABM : public ActiveBlockModifier 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"<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 */ @@ -620,8 +851,9 @@ static int l_register_tool(lua_State *L) // register_craftitem(name, {lots of stuff}) static int l_register_craftitem(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_craftitem: "<registerCraftItem(name, def); lua_pushvalue(L, table); - scriptapi_add_craftitem(L, name); + scriptapi_add_craftitem(L, name.c_str()); return 0; /* number of results */ } @@ -669,8 +901,9 @@ static int l_register_craftitem(lua_State *L) // register_node(name, {lots of stuff}) static int l_register_node(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_node: "<getWritableNodeDefManager(); + + nodedef->setAlias(name, convert_to); + + return 0; /* number of results */ +} + +// alias_tool(name, convert_to_name) +static int l_alias_tool(lua_State *L) +{ + std::string name = luaL_checkstring(L, 1); + std::string convert_to = luaL_checkstring(L, 2); + + // Get server from registry + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server"); + Server *server = (Server*)lua_touserdata(L, -1); + // And get the writable tool definition manager from the server + IWritableToolDefManager *tooldef = + server->getWritableToolDefManager(); + + tooldef->setAlias(name, convert_to); + + return 0; /* number of results */ +} + +// alias_craftitem(name, convert_to_name) +static int l_alias_craftitem(lua_State *L) +{ + std::string name = luaL_checkstring(L, 1); + std::string convert_to = luaL_checkstring(L, 2); + + // Get server from registry + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server"); + Server *server = (Server*)lua_touserdata(L, -1); + // And get the writable CraftItem definition manager from the server + IWritableCraftItemDefManager *craftitemdef = + server->getWritableCraftItemDefManager(); + + craftitemdef->setAlias(name, convert_to); + + return 0; /* number of results */ +} + // register_craft({output=item, recipe={{item00,item10},{item01,item11}}) static int l_register_craft(lua_State *L) { - infostream<<"register_craft"<getModSpec(modname); + if(!mod){ + lua_pushnil(L); + return 1; + } + lua_pushstring(L, mod->path.c_str()); + return 1; +} + static const struct luaL_Reg minetest_f [] = { {"register_nodedef_defaults", l_register_nodedef_defaults}, {"register_entity", l_register_entity}, @@ -1055,11 +1364,15 @@ static const struct luaL_Reg minetest_f [] = { {"register_node", l_register_node}, {"register_craft", l_register_craft}, {"register_abm", l_register_abm}, + {"alias_node", l_alias_node}, + {"alias_tool", l_alias_tool}, + {"alias_craftitem", l_alias_craftitem}, {"setting_get", l_setting_get}, {"setting_getbool", l_setting_getbool}, {"chat_send_all", l_chat_send_all}, {"chat_send_player", l_chat_send_player}, {"get_player_privs", l_get_player_privs}, + {"get_modpath", l_get_modpath}, {NULL, NULL} }; @@ -1198,7 +1511,7 @@ class NodeMetaRef NodeMetadata *meta = getmeta(ref); if(meta == NULL) return 0; // Do it - std::string text = lua_tostring(L, 2); + std::string text = luaL_checkstring(L, 2); meta->setText(text); reportMetadataChange(ref); return 0; @@ -1238,7 +1551,7 @@ class NodeMetaRef NodeMetadata *meta = getmeta(ref); if(meta == NULL) return 0; // Do it - std::string text = lua_tostring(L, 2); + std::string text = luaL_checkstring(L, 2); meta->setInfoText(text); reportMetadataChange(ref); return 0; @@ -1252,41 +1565,9 @@ class NodeMetaRef if(meta == NULL) return 0; // Do it Inventory *inv = meta->getInventory(); - std::string name = lua_tostring(L, 2); - // If nil, delete list - if(lua_isnil(L, 3)){ - inv->deleteList(name); - return 0; - } - // Otherwise set list - std::list items; - luaL_checktype(L, 3, LUA_TTABLE); - int table = 3; - lua_pushnil(L); - infostream<<"items: "; - 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); - infostream<<"\""<addList(name, items.size()); - int index = 0; - for(std::list::const_iterator - i = items.begin(); i != items.end(); i++){ - const std::string &itemstring = *i; - InventoryItem *newitem = NULL; - if(itemstring != "") - newitem = InventoryItem::deSerialize(itemstring, - ref->m_env->getGameDef()); - InventoryItem *olditem = invlist->changeItem(index, newitem); - delete olditem; - index++; - } + const char *name = luaL_checkstring(L, 2); + inventory_set_list_from_lua(inv, name, L, 3, + ref->m_env->getGameDef()); reportMetadataChange(ref); return 0; } @@ -1299,31 +1580,8 @@ class NodeMetaRef if(meta == NULL) return 0; // Do it Inventory *inv = meta->getInventory(); - std::string name = lua_tostring(L, 2); - InventoryList *invlist = inv->getList(name); - if(invlist == NULL){ - 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); - // Create and fill table - lua_newtable(L); - int table = lua_gettop(L); - for(u32 i=0; igetSize(); i++){ - InventoryItem *item = invlist->getItem(i); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - if(item == NULL){ - lua_pushnil(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)); - } + const char *name = luaL_checkstring(L, 2); + inventory_get_list_to_lua(inv, name, L); return 1; } @@ -1334,7 +1592,7 @@ class NodeMetaRef NodeMetadata *meta = getmeta(ref); if(meta == NULL) return 0; // Do it - std::string text = lua_tostring(L, 2); + std::string text = luaL_checkstring(L, 2); meta->setInventoryDrawSpec(text); reportMetadataChange(ref); return 0; @@ -1432,7 +1690,7 @@ class NodeMetaRef NodeMetadata *meta = getmeta(ref); if(meta == NULL) return 0; // Do it - std::string name = lua_tostring(L, 2); + std::string name = luaL_checkstring(L, 2); size_t len = 0; const char *s = lua_tolstring(L, 3, &len); std::string str(s, len); @@ -1448,7 +1706,7 @@ class NodeMetaRef NodeMetadata *meta = getmeta(ref); if(meta == NULL) return 0; // Do it - std::string name = lua_tostring(L, 2); + std::string name = luaL_checkstring(L, 2); std::string str = meta->getString(name); lua_pushlstring(L, str.c_str(), str.size()); return 1; @@ -1642,44 +1900,59 @@ class ObjectRef return 0; } - // setvelocity(self, velocity) - static int l_setvelocity(lua_State *L) + // punch(self, puncher); puncher = an another ObjectRef + static int l_punch(lua_State *L) { ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); + ObjectRef *ref2 = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *co2 = getobject(ref2); if(co == NULL) return 0; - // pos - v3f pos = readFloatPos(L, 2); + if(co2 == NULL) return 0; // Do it - co->setVelocity(pos); + co->punch(co2); return 0; } - - // setacceleration(self, acceleration) - static int l_setacceleration(lua_State *L) + + // right_click(self, clicker); clicker = an another ObjectRef + static int l_right_click(lua_State *L) { ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); + ObjectRef *ref2 = checkobject(L, 2); + ServerActiveObject *co = getobject(ref); + ServerActiveObject *co2 = getobject(ref2); if(co == NULL) return 0; - // pos - v3f pos = readFloatPos(L, 2); + if(co2 == NULL) return 0; // Do it - co->setAcceleration(pos); + co->rightClick(co2); return 0; } - - // getacceleration(self) - static int l_getacceleration(lua_State *L) + + // get_wield_digging_properties(self) + static int l_get_wield_digging_properties(lua_State *L) { ObjectRef *ref = checkobject(L, 1); - LuaEntitySAO *co = getluaobject(ref); + ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; // Do it - v3f v = co->getAcceleration(); - pushFloatPos(L, v); + ToolDiggingProperties prop; + co->getWieldDiggingProperties(&prop); + push_tool_digging_properties(L, prop); return 1; } - + + // damage_wielded_item(self, amount) + static int l_damage_wielded_item(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if(co == NULL) return 0; + // Do it + int amount = lua_tonumber(L, 2); + co->damageWieldedItem(amount); + return 0; + } + // add_to_inventory(self, itemstring) // returns: true if item was added, (false, "reason") otherwise static int l_add_to_inventory(lua_State *L) @@ -1689,7 +1962,7 @@ class ObjectRef ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; // itemstring - const char *itemstring = lua_tostring(L, 2); + const char *itemstring = luaL_checkstring(L, 2); infostream<<"ObjectRef::l_add_to_inventory(): id="<getId() <<" itemstring=\""<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: \"" + <getName()<<"\""<getRadPitch(); + float yaw = player->getRadYaw(); + v3f v(cos(pitch)*cos(yaw), sin(pitch), cos(pitch)*sin(yaw)); + push_v3f(L, v); + return 1; + } + + // get_look_pitch(self) + static int l_get_look_pitch(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadPitch()); + return 1; + } + + // get_look_yaw(self) + static int l_get_look_yaw(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + lua_pushnumber(L, player->getRadYaw()); + return 1; + } + public: ObjectRef(ServerActiveObject *object): m_object(object) @@ -1873,18 +2326,34 @@ class ObjectRef }; const char ObjectRef::className[] = "ObjectRef"; const luaL_reg ObjectRef::methods[] = { + // ServerActiveObject method(ObjectRef, remove), method(ObjectRef, getpos), method(ObjectRef, setpos), method(ObjectRef, moveto), - method(ObjectRef, setvelocity), - method(ObjectRef, setacceleration), + method(ObjectRef, punch), + method(ObjectRef, right_click), + 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_hp), method(ObjectRef, set_hp), + method(ObjectRef, get_hp), + // LuaEntitySAO-only + method(ObjectRef, setvelocity), + method(ObjectRef, setacceleration), + method(ObjectRef, getacceleration), method(ObjectRef, settexturemod), method(ObjectRef, setsprite), + // Player-only + 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), + method(ObjectRef, get_look_dir), + method(ObjectRef, get_look_pitch), + method(ObjectRef, get_look_yaw), {0,0} }; @@ -1972,18 +2441,69 @@ class EnvRef return 1; } - // EnvRef:add_luaentity(pos, entityname) + // EnvRef:get_node_or_nil(pos) + // pos = {x=num, y=num, z=num} + static int l_get_node_or_nil(lua_State *L) + { + //infostream<<"EnvRef::l_get_node()"<m_env; + if(env == NULL) return 0; + // pos + v3s16 pos = readpos(L, 2); + // Do it + try{ + MapNode n = env->getMap().getNode(pos); + // Return node + pushnode(L, n, env->getGameDef()->ndef()); + return 1; + } catch(InvalidPositionException &e) + { + lua_pushnil(L); + return 1; + } + } + + // EnvRef:get_node_light(pos, timeofday) + // pos = {x=num, y=num, z=num} + // timeofday: nil = current time, 0 = night, 0.5 = day + static int l_get_node_light(lua_State *L) + { + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + // Do it + v3s16 pos = readpos(L, 2); + u32 time_of_day = env->getTimeOfDay(); + if(lua_isnumber(L, 3)) + time_of_day = 24000.0 * lua_tonumber(L, 3); + time_of_day %= 24000; + u32 dnr = time_to_daynight_ratio(time_of_day); + MapNode n = env->getMap().getNodeNoEx(pos); + try{ + MapNode n = env->getMap().getNode(pos); + INodeDefManager *ndef = env->getGameDef()->ndef(); + lua_pushinteger(L, n.getLightBlend(dnr, ndef)); + return 1; + } catch(InvalidPositionException &e) + { + lua_pushnil(L); + return 1; + } + } + + // EnvRef:add_entity(pos, entityname) // pos = {x=num, y=num, z=num} - static int l_add_luaentity(lua_State *L) + static int l_add_entity(lua_State *L) { - //infostream<<"EnvRef::l_add_luaentity()"<m_env; if(env == NULL) return 0; // pos v3f pos = readFloatPos(L, 2); // content - const char *name = lua_tostring(L, 3); + const char *name = luaL_checkstring(L, 3); // Do it ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); env->addActiveObject(obj); @@ -2001,7 +2521,7 @@ class EnvRef // pos v3f pos = readFloatPos(L, 2); // inventorystring - const char *inventorystring = lua_tostring(L, 3); + const char *inventorystring = luaL_checkstring(L, 3); // Do it ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring); env->addActiveObject(obj); @@ -2060,7 +2580,7 @@ class EnvRef ServerEnvironment *env = o->m_env; if(env == NULL) return 0; // Do it - const char *name = lua_tostring(L, 2); + const char *name = luaL_checkstring(L, 2); ServerRemotePlayer *player = static_cast(env->getPlayer(name)); if(player == NULL){ @@ -2072,6 +2592,36 @@ class EnvRef return 1; } + // EnvRef:get_objects_inside_radius(pos, radius) + static int l_get_objects_inside_radius(lua_State *L) + { + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + // Get environemnt + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + // Do it + v3f pos = readFloatPos(L, 2); + float radius = luaL_checknumber(L, 3) * BS; + std::set ids = env->getObjectsInsideRadius(pos, radius); + lua_newtable(L); + int table = lua_gettop(L); + for(std::set::const_iterator + i = ids.begin(); i != ids.end(); i++){ + ServerActiveObject *obj = env->getActiveObject(*i); + // Insert object reference into table + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + objectref_get_or_create(L, obj); + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } + return 1; + } + static int gc_object(lua_State *L) { EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); delete o; @@ -2140,12 +2690,15 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, add_node), method(EnvRef, remove_node), method(EnvRef, get_node), - method(EnvRef, add_luaentity), + method(EnvRef, get_node_or_nil), + method(EnvRef, get_node_light), + method(EnvRef, add_entity), method(EnvRef, add_item), method(EnvRef, add_rat), method(EnvRef, add_firefly), method(EnvRef, get_meta), method(EnvRef, get_player_by_name), + method(EnvRef, get_objects_inside_radius), {0,0} }; @@ -2207,6 +2760,32 @@ void scriptapi_export(lua_State *L, Server *server) ObjectRef::Register(L); } +bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, + const std::string &modname) +{ + ModNameStorer modnamestorer(L, modname); + + if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz" + "0123456789_")){ + errorstream<<"Error loading mod \""< required_neighbors; + lua_getfield(L, current_abm, "neighbors"); + if(lua_istable(L, -1)){ + int table = lua_gettop(L); + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + required_neighbors.insert(lua_tostring(L, -1)); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + } else if(lua_isstring(L, -1)){ + required_neighbors.insert(lua_tostring(L, -1)); } lua_pop(L, 1); @@ -2266,7 +2866,7 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env) getintfield(L, current_abm, "chance", trigger_chance); LuaABM *abm = new LuaABM(L, id, trigger_contents, - trigger_interval, trigger_chance); + required_neighbors, trigger_interval, trigger_chance); env->addActiveBlockModifier(abm); @@ -2287,7 +2887,7 @@ static void dump2(lua_State *L, const char *name) 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 @@ -2365,7 +2965,7 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name, 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) @@ -2398,7 +2998,7 @@ void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player) // 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 } } @@ -2423,7 +3023,7 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player) // 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) @@ -2433,6 +3033,15 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player) 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 */ @@ -2536,7 +3145,7 @@ bool scriptapi_craftitem_on_drop(lua_State *L, const char *name, 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; @@ -2560,7 +3169,7 @@ bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name, 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; @@ -2584,7 +3193,7 @@ bool scriptapi_craftitem_on_use(lua_State *L, const char *name, 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; @@ -2614,7 +3223,7 @@ void scriptapi_environment_step(lua_State *L, float dtime) // 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 } } @@ -2649,7 +3258,7 @@ void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode, 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 } } @@ -2684,7 +3293,7 @@ void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode, 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 } } @@ -2719,7 +3328,7 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node, 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 } } @@ -2745,7 +3354,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp) 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 } } @@ -2948,9 +3557,9 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) 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)); @@ -2968,8 +3577,9 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id, 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)); }