Added player-local context and /luaclear command
parent
d1ac137bc0
commit
63d0d602c7
|
@ -0,0 +1,66 @@
|
|||
local PrintablePos =
|
||||
{
|
||||
__tostring = function(pos)
|
||||
return "(" .. pos.x .. ", " .. pos.y .. ", " .. pos.z .. ")";
|
||||
end
|
||||
};
|
||||
function PrintablePos:new(pos)
|
||||
return setmetatable(pos, self);
|
||||
end
|
||||
|
||||
local PlayerEnv =
|
||||
{
|
||||
playerContexts = setmetatable({}, { __mode = "k" }), -- weak keys
|
||||
|
||||
playerFuncs =
|
||||
{
|
||||
me = function(player)
|
||||
return player;
|
||||
end,
|
||||
|
||||
myname = function(player)
|
||||
return player:get_player_name();
|
||||
end,
|
||||
|
||||
here = function(player)
|
||||
return PrintablePos:new(player:getpos());
|
||||
end,
|
||||
|
||||
print = function(player)
|
||||
return function(...)
|
||||
local str = "";
|
||||
for _, arg in ipairs({...}) do
|
||||
str = str .. tostring(arg);
|
||||
end
|
||||
minetest.chat_send_player(player:get_player_name(), str, false);
|
||||
end
|
||||
end
|
||||
};
|
||||
};
|
||||
|
||||
function PlayerEnv:new(player)
|
||||
local env = {};
|
||||
self.playerContexts[env] = player;
|
||||
setmetatable(env, self);
|
||||
return env;
|
||||
end
|
||||
setmetatable(PlayerEnv, { __call = PlayerEnv.new });
|
||||
|
||||
function PlayerEnv.__index(env, key)
|
||||
local playerFunc = PlayerEnv.playerFuncs[key];
|
||||
if playerFunc then
|
||||
local player = PlayerEnv.playerContexts[env];
|
||||
return playerFunc(player);
|
||||
else
|
||||
return _G[key];
|
||||
end
|
||||
end
|
||||
|
||||
function PlayerEnv.__newindex(env, key, value)
|
||||
if PlayerEnv.playerFuncs[key] then
|
||||
error("cannot set special '"..key.."' player variable");
|
||||
end
|
||||
rawset(env, key, value);
|
||||
end
|
||||
|
||||
return PlayerEnv;
|
14
README.txt
14
README.txt
|
@ -36,7 +36,9 @@ Required Minetest Version: (tested in 0.4.9)
|
|||
|
||||
Dependencies: (none)
|
||||
|
||||
Commands: /lua <luaStatement>
|
||||
Commands:
|
||||
* /lua <luaStatement>
|
||||
* /luaclear
|
||||
|
||||
Privileges: lua
|
||||
|
||||
|
@ -64,6 +66,16 @@ Try the following commands:
|
|||
/lua print(myname);
|
||||
/lua print(here);
|
||||
|
||||
Version 1.2
|
||||
|
||||
* Release 2014-07-04
|
||||
* Keeps "global" variables set by commands in a player-local context.
|
||||
* Prevents setting of special variables (e.g. me, myname, here, print).
|
||||
* Added /luaclear command to clear the player-local context.
|
||||
|
||||
To set true globals visible to mods and other players, use "_G.var = ...". Can
|
||||
also be used to get any globals hidden by specials and player-local variables.
|
||||
|
||||
Copyright and Licensing
|
||||
-----------------------
|
||||
|
||||
|
|
81
init.lua
81
init.lua
|
@ -1,16 +1,30 @@
|
|||
local function copyTable(t)
|
||||
if type(t) ~= "table" then return t; end
|
||||
local tc = {};
|
||||
for k, v in pairs(t) do
|
||||
tc[k] = v;
|
||||
end
|
||||
return tc;
|
||||
end
|
||||
local MOD_NAME = minetest.get_current_modname();
|
||||
local MOD_PATH = minetest.get_modpath(MOD_NAME);
|
||||
|
||||
local function posToStr(pos)
|
||||
return "(" .. pos.x .. ", " ..pos.y.. ", " .. pos.z .. ")";
|
||||
local PlayerEnv = dofile(MOD_PATH.."/PlayerEnv.lua");
|
||||
|
||||
local playerEnvs = {};
|
||||
minetest.register_on_leaveplayer(
|
||||
function(player)
|
||||
playerEnvs[player:get_player_name()] = nil;
|
||||
end);
|
||||
|
||||
local function runLuaCmd(playerName, paramStr)
|
||||
local cmdFunc, errMsg = loadstring(paramStr, "/lua command");
|
||||
if not cmdFunc then
|
||||
error(errMsg);
|
||||
end
|
||||
|
||||
local playerEnv = playerEnvs[playerName];
|
||||
if not playerEnv then
|
||||
local player = minetest.get_player_by_name(playerName);
|
||||
playerEnv = PlayerEnv:new(player);
|
||||
playerEnvs[playerName] = playerEnv;
|
||||
end
|
||||
|
||||
setfenv(cmdFunc, playerEnv);
|
||||
cmdFunc();
|
||||
end
|
||||
local posMeta = { __tostring = posToStr };
|
||||
|
||||
minetest.register_privilege(
|
||||
"lua",
|
||||
|
@ -26,37 +40,22 @@ minetest.register_chatcommand(
|
|||
description = "Executes a lua statement (chunk), for debugging.",
|
||||
privs = { lua = true },
|
||||
func =
|
||||
function(name, param)
|
||||
local cmdFunc, success, errMsg;
|
||||
|
||||
cmdFunc, errMsg = loadstring(param, "/lua command");
|
||||
if not cmdFunc then
|
||||
minetest.chat_send_player(name, "ERROR: "..errMsg);
|
||||
return;
|
||||
end
|
||||
|
||||
local player = minetest.get_player_by_name(name);
|
||||
local pos = player:getpos();
|
||||
setmetatable(pos, posMeta);
|
||||
|
||||
local env = copyTable(getfenv(0));
|
||||
env.print =
|
||||
function(...)
|
||||
str = "";
|
||||
for _, arg in ipairs({...}) do
|
||||
str = str .. tostring(arg);
|
||||
end
|
||||
minetest.chat_send_player(name, str, false);
|
||||
end;
|
||||
env.myname = name;
|
||||
env.me = player;
|
||||
env.here = pos;
|
||||
|
||||
setfenv(cmdFunc, env);
|
||||
|
||||
success, errMsg = pcall(cmdFunc);
|
||||
function(playerName, paramStr)
|
||||
local success, errMsg = pcall(runLuaCmd, playerName, paramStr);
|
||||
if not success then
|
||||
minetest.chat_send_player(name, "ERROR: "..errMsg);
|
||||
minetest.chat_send_player(playerName, "ERROR: "..errMsg);
|
||||
end
|
||||
end
|
||||
});
|
||||
|
||||
minetest.register_chatcommand(
|
||||
"luaclear",
|
||||
{
|
||||
params = "",
|
||||
description = "Clears all variables in your /lua player context",
|
||||
privs = { lua = true },
|
||||
func =
|
||||
function(playerName, paramStr)
|
||||
playerEnvs[playerName] = nil;
|
||||
end
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue