summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/builtin.lua149
-rw-r--r--data/mods/default/init.lua61
-rw-r--r--data/mods/experimental/init.lua146
-rw-r--r--src/auth.cpp24
-rw-r--r--src/auth.h6
-rw-r--r--src/scriptapi.cpp530
6 files changed, 534 insertions, 382 deletions
diff --git a/data/builtin.lua b/data/builtin.lua
index 5f5d40f67..dc41caf69 100644
--- a/data/builtin.lua
+++ b/data/builtin.lua
@@ -148,6 +148,155 @@ minetest.register_node("ignore", {
})
--
+-- 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 395e4a64c..f9c4c8231 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 45f16738f..fdfc8a780 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 dc740411b..684391654 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<std::string> privsToSet(u64 privs)
+{
+ std::set<std::string> 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 5ea697a6a..9939632a9 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 <set>
#include <string>
#include <jthread.h>
#include <jmutex.h>
-#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<std::string> 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 83efef670..06cf38d1e 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<std::string> privs_s = privsToSet(privs_i);
+ for(std::set<std::string>::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}
};
@@ -1503,236 +1528,6 @@ const luaL_reg NodeMetaRef::methods[] = {
};
/*
- 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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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()"<<std::endl;
- EnvRef *o = checkobject(L, 1);
- ServerEnvironment *env = o->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"<<std::endl;
- }
-
- ~EnvRef()
- {
- infostream<<"EnvRef destructing"<<std::endl;
- }
-
- // Creates an EnvRef and leaves it on top of stack
- // Not callable from Lua; all references are created on the C side.
- static void create(lua_State *L, ServerEnvironment *env)
- {
- EnvRef *o = new EnvRef(env);
- //infostream<<"EnvRef::create: o="<<o<<std::endl;
- *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
- luaL_getmetatable(L, className);
- lua_setmetatable(L, -2);
- }
-
- static void set_null(lua_State *L)
- {
- EnvRef *o = checkobject(L, -1);
- o->m_env = NULL;
- }
-
- static void Register(lua_State *L)
- {
- lua_newtable(L);
- int methodtable = lua_gettop(L);
- luaL_newmetatable(L, className);
- int metatable = lua_gettop(L);
-
- lua_pushliteral(L, "__metatable");
- lua_pushvalue(L, methodtable);
- lua_settable(L, metatable); // hide metatable from Lua getmetatable()
-
- lua_pushliteral(L, "__index");
- lua_pushvalue(L, methodtable);
- lua_settable(L, metatable);
-
- lua_pushliteral(L, "__gc");
- lua_pushcfunction(L, gc_object);
- lua_settable(L, metatable);
-
- lua_pop(L, 1); // drop metatable
-
- luaL_openlib(L, 0, methods, 0); // fill methodtable
- lua_pop(L, 1); // drop methodtable
-
- // Cannot be created from Lua
- //lua_register(L, className, create_object);
- }
-};
-const char EnvRef::className[] = "EnvRef";
-const luaL_reg EnvRef::methods[] = {
- method(EnvRef, add_node),
- method(EnvRef, remove_node),
- method(EnvRef, get_node),
- method(EnvRef, add_luaentity),
- method(EnvRef, add_item),
- method(EnvRef, add_rat),
- method(EnvRef, add_firefly),
- method(EnvRef, get_meta),
- {0,0}
-};
-
-/*
ObjectRef
*/
@@ -1886,7 +1681,7 @@ private:
}
// add_to_inventory(self, itemstring)
- // returns: true if item was added, false otherwise
+ // returns: true if item was added, (false, "reason") otherwise
static int l_add_to_inventory(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
@@ -1902,12 +1697,23 @@ private:
ServerEnvironment *env = co->getEnv();
assert(env);
IGameDef *gamedef = env->getGameDef();
- InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
- infostream<<"item="<<env<<std::endl;
- bool fits = co->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)
@@ -2094,6 +1900,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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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()"<<std::endl;
+ EnvRef *o = checkobject(L, 1);
+ ServerEnvironment *env = o->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<ServerRemotePlayer*>(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"<<std::endl;
+ }
+
+ ~EnvRef()
+ {
+ infostream<<"EnvRef destructing"<<std::endl;
+ }
+
+ // Creates an EnvRef and leaves it on top of stack
+ // Not callable from Lua; all references are created on the C side.
+ static void create(lua_State *L, ServerEnvironment *env)
+ {
+ EnvRef *o = new EnvRef(env);
+ //infostream<<"EnvRef::create: o="<<o<<std::endl;
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ }
+
+ static void set_null(lua_State *L)
+ {
+ EnvRef *o = checkobject(L, -1);
+ o->m_env = NULL;
+ }
+
+ static void Register(lua_State *L)
+ {
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Cannot be created from Lua
+ //lua_register(L, className, create_object);
+ }
+};
+const char EnvRef::className[] = "EnvRef";
+const luaL_reg EnvRef::methods[] = {
+ method(EnvRef, add_node),
+ method(EnvRef, remove_node),
+ method(EnvRef, get_node),
+ method(EnvRef, add_luaentity),
+ method(EnvRef, add_item),
+ method(EnvRef, add_rat),
+ method(EnvRef, add_firefly),
+ method(EnvRef, get_meta),
+ method(EnvRef, get_player_by_name),
+ {0,0}
+};
+
+/*
Main export function
*/