From 103d4793f00b2dd592739f686e90370c2d8953a3 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Tue, 29 Nov 2011 21:30:22 +0200 Subject: [PATCH] Create the necessary API for /giveme and /give and implement those commands; also sort out the scripts a bit --- data/builtin.lua | 149 +++++++++ data/mods/default/init.lua | 61 ++++ data/mods/experimental/init.lua | 146 +-------- src/auth.cpp | 24 ++ src/auth.h | 6 +- src/scriptapi.cpp | 530 ++++++++++++++++++-------------- 6 files changed, 534 insertions(+), 382 deletions(-) diff --git a/data/builtin.lua b/data/builtin.lua index 5f5d40f6..dc41caf6 100644 --- a/data/builtin.lua +++ b/data/builtin.lua @@ -147,6 +147,155 @@ minetest.register_node("ignore", { air_equivalent = true, }) +-- +-- stackstring manipulation functions +-- example stackstring: 'CraftItem "apple" 4' +-- example item: {type="CraftItem", name="apple"} +-- example item: {type="ToolItem", name="SteelPick", wear="23272"} +-- + +function stackstring_take_item(stackstring) + if stackstring == nil then + return '', nil + end + local stacktype = nil + stacktype = string.match(stackstring, + '([%a%d]+Item[%a%d]*)') + if stacktype == "NodeItem" or stacktype == "CraftItem" then + local itemtype = nil + local itemname = nil + local itemcount = nil + itemtype, itemname, itemcount = string.match(stackstring, + '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') + itemcount = tonumber(itemcount) + if itemcount == 0 then + return '', nil + elseif itemcount == 1 then + return '', {type=itemtype, name=itemname} + else + return itemtype.." \""..itemname.."\" "..(itemcount-1), + {type=itemtype, name=itemname} + end + elseif stacktype == "ToolItem" then + local itemtype = nil + local itemname = nil + local itemwear = nil + itemtype, itemname, itemwear = string.match(stackstring, + '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') + itemwear = tonumber(itemwear) + return '', {type=itemtype, name=itemname, wear=itemwear} + end +end + +function stackstring_put_item(stackstring, item) + if item == nil then + return stackstring, false + end + stackstring = stackstring or '' + local stacktype = nil + stacktype = string.match(stackstring, + '([%a%d]+Item[%a%d]*)') + stacktype = stacktype or '' + if stacktype ~= '' and stacktype ~= item.type then + return stackstring, false + end + if item.type == "NodeItem" or item.type == "CraftItem" then + local itemtype = nil + local itemname = nil + local itemcount = nil + itemtype, itemname, itemcount = string.match(stackstring, + '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') + itemtype = itemtype or item.type + itemname = itemname or item.name + if itemcount == nil then + itemcount = 0 + end + itemcount = itemcount + 1 + return itemtype.." \""..itemname.."\" "..itemcount, true + elseif item.type == "ToolItem" then + if stacktype ~= nil then + return stackstring, false + end + local itemtype = nil + local itemname = nil + local itemwear = nil + itemtype, itemname, itemwear = string.match(stackstring, + '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') + itemwear = tonumber(itemwear) + return itemtype.." \""..itemname.."\" "..itemwear, true + end + return stackstring, false +end + +function stackstring_put_stackstring(stackstring, src) + while src ~= '' do + --print("src="..dump(src)) + src, item = stackstring_take_item(src) + --print("src="..dump(src).." item="..dump(item)) + local success + stackstring, success = stackstring_put_item(stackstring, item) + if not success then + return stackstring, false + end + end + return stackstring, true +end + +function test_stackstring() + local stack + local item + local success + + stack, item = stackstring_take_item('NodeItem "TNT" 3') + assert(stack == 'NodeItem "TNT" 2') + assert(item.type == 'NodeItem') + assert(item.name == 'TNT') + + stack, item = stackstring_take_item('CraftItem "with spaces" 2') + assert(stack == 'CraftItem "with spaces" 1') + assert(item.type == 'CraftItem') + assert(item.name == 'with spaces') + + stack, item = stackstring_take_item('CraftItem "with spaces" 1') + assert(stack == '') + assert(item.type == 'CraftItem') + assert(item.name == 'with spaces') + + stack, item = stackstring_take_item('CraftItem "s8df2kj3" 0') + assert(stack == '') + assert(item == nil) + + stack, item = stackstring_take_item('ToolItem "With Spaces" 32487') + assert(stack == '') + assert(item.type == 'ToolItem') + assert(item.name == 'With Spaces') + assert(item.wear == 32487) + + stack, success = stackstring_put_item('NodeItem "With Spaces" 40', + {type='NodeItem', name='With Spaces'}) + assert(stack == 'NodeItem "With Spaces" 41') + assert(success == true) + + stack, success = stackstring_put_item('CraftItem "With Spaces" 40', + {type='CraftItem', name='With Spaces'}) + assert(stack == 'CraftItem "With Spaces" 41') + assert(success == true) + + stack, success = stackstring_put_item('ToolItem "With Spaces" 32487', + {type='ToolItem', name='With Spaces'}) + assert(stack == 'ToolItem "With Spaces" 32487') + assert(success == false) + + stack, success = stackstring_put_item('NodeItem "With Spaces" 40', + {type='ToolItem', name='With Spaces'}) + assert(stack == 'NodeItem "With Spaces" 40') + assert(success == false) + + assert(stackstring_put_stackstring('NodeItem "With Spaces" 2', + 'NodeItem "With Spaces" 1') == 'NodeItem "With Spaces" 3') +end +test_stackstring() + -- -- Callback registration -- diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua index 395e4a64..f9c4c823 100644 --- a/data/mods/default/init.lua +++ b/data/mods/default/init.lua @@ -26,6 +26,7 @@ -- minetest.setting_getbool(name) -- minetest.chat_send_all(text) -- minetest.chat_send_player(name, text) +-- minetest.get_player_privs(name) -- -- Global objects: -- minetest.env - environment reference @@ -52,6 +53,7 @@ -- - add_rat(pos) -- - add_firefly(pos) -- - get_meta(pos) -- Get a NodeMetaRef at that position +-- - get_player_by_name(name) -- Get an ObjectRef to a player -- -- NodeMetaRef -- - get_type() @@ -1322,6 +1324,65 @@ function on_punchnode(p, node) end minetest.register_on_punchnode(on_punchnode) +minetest.register_on_chat_message(function(name, message) + print("default on_chat_message: name="..dump(name).." message="..dump(message)) + local cmd = "/giveme" + if message:sub(0, #cmd) == cmd then + if not minetest.get_player_privs(name)["give"] then + minetest.chat_send_player(name, "you don't have permission to give") + return true -- Handled chat message + end + stackstring = string.match(message, cmd.." (.*)") + if stackstring == nil then + minetest.chat_send_player(name, 'usage: '..cmd..' stackstring') + return true -- Handled chat message + end + print(cmd..' invoked, stackstring="'..stackstring..'"') + player = minetest.env:get_player_by_name(name) + added, error_msg = player:add_to_inventory(stackstring) + if added then + minetest.chat_send_player(name, '"'..stackstring + ..'" added to inventory.'); + else + minetest.chat_send_player(name, 'Could not give "'..stackstring + ..'": '..error_msg); + end + return true -- Handled chat message + end + local cmd = "/give" + if message:sub(0, #cmd) == cmd then + print("minetest.get_player_privs(name)=" + ..dump(minetest.get_player_privs(name))) + if not minetest.get_player_privs(name)["give"] then + minetest.chat_send_player(name, "you don't have permission to give") + return true -- Handled chat message + end + name2, stackstring = string.match(message, cmd.." ([%a%d_-]+) (.*)") + if name == nil or stackstring == nil then + minetest.chat_send_player(name, 'usage: '..cmd..' name stackstring') + return true -- Handled chat message + end + print(cmd..' invoked, name2="'..name2 + ..'" stackstring="'..stackstring..'"') + player = minetest.env:get_player_by_name(name2) + if player == nil then + minetest.chat_send_player(name, name2..' is not a known player') + return true -- Handled chat message + end + added, error_msg = player:add_to_inventory(stackstring) + if added then + minetest.chat_send_player(name, '"'..stackstring + ..'" added to '..name2..'\'s inventory.'); + minetest.chat_send_player(name2, '"'..stackstring + ..'" added to inventory.'); + else + minetest.chat_send_player(name, 'Could not give "'..stackstring + ..'": '..error_msg); + end + return true -- Handled chat message + end +end) + -- -- Done, print some random stuff -- diff --git a/data/mods/experimental/init.lua b/data/mods/experimental/init.lua index 45f16738..fdfc8a78 100644 --- a/data/mods/experimental/init.lua +++ b/data/mods/experimental/init.lua @@ -41,148 +41,6 @@ minetest.register_on_placenode(function(pos, newnode, placer) end end) -function stackstring_take_item(stackstring) - if stackstring == nil then - return '', nil - end - local stacktype = nil - stacktype = string.match(stackstring, - '([%a%d]+Item[%a%d]*)') - if stacktype == "NodeItem" or stacktype == "CraftItem" then - local itemtype = nil - local itemname = nil - local itemcount = nil - itemtype, itemname, itemcount = string.match(stackstring, - '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') - itemcount = tonumber(itemcount) - if itemcount == 0 then - return '', nil - elseif itemcount == 1 then - return '', {type=itemtype, name=itemname} - else - return itemtype.." \""..itemname.."\" "..(itemcount-1), - {type=itemtype, name=itemname} - end - elseif stacktype == "ToolItem" then - local itemtype = nil - local itemname = nil - local itemwear = nil - itemtype, itemname, itemwear = string.match(stackstring, - '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') - itemwear = tonumber(itemwear) - return '', {type=itemtype, name=itemname, wear=itemwear} - end -end - -function stackstring_put_item(stackstring, item) - if item == nil then - return stackstring, false - end - stackstring = stackstring or '' - local stacktype = nil - stacktype = string.match(stackstring, - '([%a%d]+Item[%a%d]*)') - stacktype = stacktype or '' - if stacktype ~= '' and stacktype ~= item.type then - return stackstring, false - end - if item.type == "NodeItem" or item.type == "CraftItem" then - local itemtype = nil - local itemname = nil - local itemcount = nil - itemtype, itemname, itemcount = string.match(stackstring, - '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') - itemtype = itemtype or item.type - itemname = itemname or item.name - if itemcount == nil then - itemcount = 0 - end - itemcount = itemcount + 1 - return itemtype.." \""..itemname.."\" "..itemcount, true - elseif item.type == "ToolItem" then - if stacktype ~= nil then - return stackstring, false - end - local itemtype = nil - local itemname = nil - local itemwear = nil - itemtype, itemname, itemwear = string.match(stackstring, - '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)') - itemwear = tonumber(itemwear) - return itemtype.." \""..itemname.."\" "..itemwear, true - end - return stackstring, false -end - -function stackstring_put_stackstring(stackstring, src) - while src ~= '' do - --print("src="..dump(src)) - src, item = stackstring_take_item(src) - --print("src="..dump(src).." item="..dump(item)) - local success - stackstring, success = stackstring_put_item(stackstring, item) - if not success then - return stackstring, false - end - end - return stackstring, true -end - -function test_stack() - local stack - local item - local success - - stack, item = stackstring_take_item('NodeItem "TNT" 3') - assert(stack == 'NodeItem "TNT" 2') - assert(item.type == 'NodeItem') - assert(item.name == 'TNT') - - stack, item = stackstring_take_item('CraftItem "with spaces" 2') - assert(stack == 'CraftItem "with spaces" 1') - assert(item.type == 'CraftItem') - assert(item.name == 'with spaces') - - stack, item = stackstring_take_item('CraftItem "with spaces" 1') - assert(stack == '') - assert(item.type == 'CraftItem') - assert(item.name == 'with spaces') - - stack, item = stackstring_take_item('CraftItem "s8df2kj3" 0') - assert(stack == '') - assert(item == nil) - - stack, item = stackstring_take_item('ToolItem "With Spaces" 32487') - assert(stack == '') - assert(item.type == 'ToolItem') - assert(item.name == 'With Spaces') - assert(item.wear == 32487) - - stack, success = stackstring_put_item('NodeItem "With Spaces" 40', - {type='NodeItem', name='With Spaces'}) - assert(stack == 'NodeItem "With Spaces" 41') - assert(success == true) - - stack, success = stackstring_put_item('CraftItem "With Spaces" 40', - {type='CraftItem', name='With Spaces'}) - assert(stack == 'CraftItem "With Spaces" 41') - assert(success == true) - - stack, success = stackstring_put_item('ToolItem "With Spaces" 32487', - {type='ToolItem', name='With Spaces'}) - assert(stack == 'ToolItem "With Spaces" 32487') - assert(success == false) - - stack, success = stackstring_put_item('NodeItem "With Spaces" 40', - {type='ToolItem', name='With Spaces'}) - assert(stack == 'NodeItem "With Spaces" 40') - assert(success == false) - - assert(stackstring_put_stackstring('NodeItem "With Spaces" 2', - 'NodeItem "With Spaces" 1') == 'NodeItem "With Spaces" 3') -end -test_stack() - minetest.register_abm({ nodenames = {"luafurnace"}, interval = 1.0, @@ -426,7 +284,7 @@ print("setting max_users = " .. dump(minetest.setting_get("max_users"))) print("setting asdf = " .. dump(minetest.setting_get("asdf"))) minetest.register_on_chat_message(function(name, message) - print("on_chat_message: name="..dump(name).." message="..dump(message)) + --[[print("on_chat_message: name="..dump(name).." message="..dump(message)) local cmd = "/testcommand" if message:sub(0, #cmd) == cmd then print(cmd.." invoked") @@ -437,7 +295,7 @@ minetest.register_on_chat_message(function(name, message) print("script-overridden help command") minetest.chat_send_all("script-overridden help command") return true - end + end]] end) -- Grow papyrus on TNT every 10 seconds diff --git a/src/auth.cpp b/src/auth.cpp index dc740411..68439165 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -25,6 +25,26 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "strfnd.h" #include "debug.h" +std::set privsToSet(u64 privs) +{ + std::set s; + if(privs & PRIV_BUILD) + s.insert("build"); + if(privs & PRIV_TELEPORT) + s.insert("teleport"); + if(privs & PRIV_SETTIME) + s.insert("settime"); + if(privs & PRIV_PRIVS) + s.insert("privs"); + if(privs & PRIV_SHOUT) + s.insert("shout"); + if(privs & PRIV_BAN) + s.insert("ban"); + if(privs & PRIV_GIVE) + s.insert("give"); + return s; +} + // Convert a privileges value into a human-readable string, // with each component separated by a comma. std::string privsToString(u64 privs) @@ -42,6 +62,8 @@ std::string privsToString(u64 privs) os<<"shout,"; if(privs & PRIV_BAN) os<<"ban,"; + if(privs & PRIV_GIVE) + os<<"give,"; if(os.tellp()) { // Drop the trailing comma. (Why on earth can't @@ -74,6 +96,8 @@ u64 stringToPrivs(std::string str) privs |= PRIV_SHOUT; else if(s == "ban") privs |= PRIV_BAN; + else if(s == "give") + privs |= PRIV_GIVE; else return PRIV_INVALID; } diff --git a/src/auth.h b/src/auth.h index 5ea697a6..9939632a 100644 --- a/src/auth.h +++ b/src/auth.h @@ -20,10 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef AUTH_HEADER #define AUTH_HEADER +#include #include #include #include -#include "common_irrlicht.h" +#include "irrlichttypes.h" #include "exceptions.h" // Player privileges. These form a bitmask stored in the privs field @@ -39,6 +40,7 @@ const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all // players const u64 PRIV_BAN = 64; // Can ban players +const u64 PRIV_GIVE = 128; // Can give stuff // Default privileges - these can be overriden for new players using the // config option "default_privs" - however, this value still applies for @@ -47,6 +49,8 @@ const u64 PRIV_DEFAULT = PRIV_BUILD|PRIV_SHOUT; const u64 PRIV_ALL = 0x7FFFFFFFFFFFFFFFULL; const u64 PRIV_INVALID = 0x8000000000000000ULL; +std::set privsToSet(u64 privs); + // Convert a privileges value into a human-readable string, // with each component separated by a comma. std::string privsToString(u64 privs); diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 83efef67..06cf38d1 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -1023,6 +1023,30 @@ static int l_chat_send_player(lua_State *L) return 0; } +// get_player_privs(name, text) +static int l_get_player_privs(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + // Get server from registry + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server"); + Server *server = (Server*)lua_touserdata(L, -1); + // Do it + lua_newtable(L); + int table = lua_gettop(L); + u64 privs_i = server->getPlayerAuthPrivs(name); + // Special case for the "name" setting (local player / server owner) + if(name == g_settings->get("name")) + privs_i = PRIV_ALL; + std::set privs_s = privsToSet(privs_i); + for(std::set::const_iterator + i = privs_s.begin(); i != privs_s.end(); i++){ + lua_pushboolean(L, true); + lua_setfield(L, table, i->c_str()); + } + lua_pushvalue(L, table); + return 1; +} + static const struct luaL_Reg minetest_f [] = { {"register_nodedef_defaults", l_register_nodedef_defaults}, {"register_entity", l_register_entity}, @@ -1035,6 +1059,7 @@ static const struct luaL_Reg minetest_f [] = { {"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}, {NULL, NULL} }; @@ -1502,236 +1527,6 @@ const luaL_reg NodeMetaRef::methods[] = { {0,0} }; -/* - EnvRef -*/ - -class EnvRef -{ -private: - ServerEnvironment *m_env; - - static const char className[]; - static const luaL_reg methods[]; - - static EnvRef *checkobject(lua_State *L, int narg) - { - luaL_checktype(L, narg, LUA_TUSERDATA); - void *ud = luaL_checkudata(L, narg, className); - if(!ud) luaL_typerror(L, narg, className); - return *(EnvRef**)ud; // unbox pointer - } - - // Exported functions - - // EnvRef:add_node(pos, node) - // pos = {x=num, y=num, z=num} - static int l_add_node(lua_State *L) - { - //infostream<<"EnvRef::l_add_node()"<m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = readpos(L, 2); - // content - MapNode n = readnode(L, 3, env->getGameDef()->ndef()); - // Do it - bool succeeded = env->getMap().addNodeWithEvent(pos, n); - lua_pushboolean(L, succeeded); - return 1; - } - - // EnvRef:remove_node(pos) - // pos = {x=num, y=num, z=num} - static int l_remove_node(lua_State *L) - { - //infostream<<"EnvRef::l_remove_node()"<m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = readpos(L, 2); - // Do it - bool succeeded = env->getMap().removeNodeWithEvent(pos); - lua_pushboolean(L, succeeded); - return 1; - } - - // EnvRef:get_node(pos) - // pos = {x=num, y=num, z=num} - static int l_get_node(lua_State *L) - { - //infostream<<"EnvRef::l_get_node()"<m_env; - if(env == NULL) return 0; - // pos - v3s16 pos = readpos(L, 2); - // Do it - MapNode n = env->getMap().getNodeNoEx(pos); - // Return node - pushnode(L, n, env->getGameDef()->ndef()); - return 1; - } - - // EnvRef:add_luaentity(pos, entityname) - // pos = {x=num, y=num, z=num} - static int l_add_luaentity(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); - // Do it - ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); - env->addActiveObject(obj); - return 0; - } - - // EnvRef:add_item(pos, inventorystring) - // pos = {x=num, y=num, z=num} - static int l_add_item(lua_State *L) - { - infostream<<"EnvRef::l_add_item()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = readFloatPos(L, 2); - // inventorystring - const char *inventorystring = lua_tostring(L, 3); - // Do it - ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring); - env->addActiveObject(obj); - return 0; - } - - // EnvRef:add_rat(pos) - // pos = {x=num, y=num, z=num} - static int l_add_rat(lua_State *L) - { - infostream<<"EnvRef::l_add_rat()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = readFloatPos(L, 2); - // Do it - ServerActiveObject *obj = new RatSAO(env, pos); - env->addActiveObject(obj); - return 0; - } - - // EnvRef:add_firefly(pos) - // pos = {x=num, y=num, z=num} - static int l_add_firefly(lua_State *L) - { - infostream<<"EnvRef::l_add_firefly()"<m_env; - if(env == NULL) return 0; - // pos - v3f pos = readFloatPos(L, 2); - // Do it - ServerActiveObject *obj = new FireflySAO(env, pos); - env->addActiveObject(obj); - return 0; - } - - // EnvRef:get_meta(pos) - static int l_get_meta(lua_State *L) - { - //infostream<<"EnvRef::l_get_meta()"<m_env; - if(env == NULL) return 0; - // Do it - v3s16 p = readpos(L, 2); - NodeMetaRef::create(L, p, env); - return 1; - } - - static int gc_object(lua_State *L) { - EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); - delete o; - return 0; - } - -public: - EnvRef(ServerEnvironment *env): - m_env(env) - { - infostream<<"EnvRef created"<getEnv(); assert(env); IGameDef *gamedef = env->getGameDef(); - InventoryItem *item = InventoryItem::deSerialize(is, gamedef); - infostream<<"item="<addToInventory(item); - // Return - lua_pushboolean(L, fits); - return 1; + try{ + InventoryItem *item = InventoryItem::deSerialize(is, gamedef); + if(item->getCount() == 0) + item->setCount(1); + bool added = co->addToInventory(item); + // Return + lua_pushboolean(L, added); + if(!added) + lua_pushstring(L, "does not fit"); + return 2; + } catch(SerializationError &e){ + // Return + lua_pushboolean(L, false); + lua_pushstring(L, (std::string("Invalid item: ") + + e.what()).c_str()); + return 2; + } } // add_to_inventory_later(self, itemstring) @@ -2093,6 +1899,256 @@ static void objectref_get_or_create(lua_State *L, } } +/* + EnvRef +*/ + +class EnvRef +{ +private: + ServerEnvironment *m_env; + + static const char className[]; + static const luaL_reg methods[]; + + static EnvRef *checkobject(lua_State *L, int narg) + { + luaL_checktype(L, narg, LUA_TUSERDATA); + void *ud = luaL_checkudata(L, narg, className); + if(!ud) luaL_typerror(L, narg, className); + return *(EnvRef**)ud; // unbox pointer + } + + // Exported functions + + // EnvRef:add_node(pos, node) + // pos = {x=num, y=num, z=num} + static int l_add_node(lua_State *L) + { + //infostream<<"EnvRef::l_add_node()"<m_env; + if(env == NULL) return 0; + // pos + v3s16 pos = readpos(L, 2); + // content + MapNode n = readnode(L, 3, env->getGameDef()->ndef()); + // Do it + bool succeeded = env->getMap().addNodeWithEvent(pos, n); + lua_pushboolean(L, succeeded); + return 1; + } + + // EnvRef:remove_node(pos) + // pos = {x=num, y=num, z=num} + static int l_remove_node(lua_State *L) + { + //infostream<<"EnvRef::l_remove_node()"<m_env; + if(env == NULL) return 0; + // pos + v3s16 pos = readpos(L, 2); + // Do it + bool succeeded = env->getMap().removeNodeWithEvent(pos); + lua_pushboolean(L, succeeded); + return 1; + } + + // EnvRef:get_node(pos) + // pos = {x=num, y=num, z=num} + static int l_get_node(lua_State *L) + { + //infostream<<"EnvRef::l_get_node()"<m_env; + if(env == NULL) return 0; + // pos + v3s16 pos = readpos(L, 2); + // Do it + MapNode n = env->getMap().getNodeNoEx(pos); + // Return node + pushnode(L, n, env->getGameDef()->ndef()); + return 1; + } + + // EnvRef:add_luaentity(pos, entityname) + // pos = {x=num, y=num, z=num} + static int l_add_luaentity(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); + // Do it + ServerActiveObject *obj = new LuaEntitySAO(env, pos, name, ""); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:add_item(pos, inventorystring) + // pos = {x=num, y=num, z=num} + static int l_add_item(lua_State *L) + { + infostream<<"EnvRef::l_add_item()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // inventorystring + const char *inventorystring = lua_tostring(L, 3); + // Do it + ServerActiveObject *obj = new ItemSAO(env, pos, inventorystring); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:add_rat(pos) + // pos = {x=num, y=num, z=num} + static int l_add_rat(lua_State *L) + { + infostream<<"EnvRef::l_add_rat()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // Do it + ServerActiveObject *obj = new RatSAO(env, pos); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:add_firefly(pos) + // pos = {x=num, y=num, z=num} + static int l_add_firefly(lua_State *L) + { + infostream<<"EnvRef::l_add_firefly()"<m_env; + if(env == NULL) return 0; + // pos + v3f pos = readFloatPos(L, 2); + // Do it + ServerActiveObject *obj = new FireflySAO(env, pos); + env->addActiveObject(obj); + return 0; + } + + // EnvRef:get_meta(pos) + static int l_get_meta(lua_State *L) + { + //infostream<<"EnvRef::l_get_meta()"<m_env; + if(env == NULL) return 0; + // Do it + v3s16 p = readpos(L, 2); + NodeMetaRef::create(L, p, env); + return 1; + } + + // EnvRef:get_player_by_name(name) + static int l_get_player_by_name(lua_State *L) + { + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if(env == NULL) return 0; + // Do it + const char *name = lua_tostring(L, 2); + ServerRemotePlayer *player = + static_cast(env->getPlayer(name)); + if(player == NULL){ + lua_pushnil(L); + return 1; + } + // Put player on stack + objectref_get_or_create(L, player); + return 1; + } + + static int gc_object(lua_State *L) { + EnvRef *o = *(EnvRef **)(lua_touserdata(L, 1)); + delete o; + return 0; + } + +public: + EnvRef(ServerEnvironment *env): + m_env(env) + { + infostream<<"EnvRef created"<