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)
|
Dependencies: (none)
|
||||||
|
|
||||||
Commands: /lua <luaStatement>
|
Commands:
|
||||||
|
* /lua <luaStatement>
|
||||||
|
* /luaclear
|
||||||
|
|
||||||
Privileges: lua
|
Privileges: lua
|
||||||
|
|
||||||
|
@ -64,6 +66,16 @@ Try the following commands:
|
||||||
/lua print(myname);
|
/lua print(myname);
|
||||||
/lua print(here);
|
/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
|
Copyright and Licensing
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
81
init.lua
81
init.lua
|
@ -1,16 +1,30 @@
|
||||||
local function copyTable(t)
|
local MOD_NAME = minetest.get_current_modname();
|
||||||
if type(t) ~= "table" then return t; end
|
local MOD_PATH = minetest.get_modpath(MOD_NAME);
|
||||||
local tc = {};
|
|
||||||
for k, v in pairs(t) do
|
|
||||||
tc[k] = v;
|
|
||||||
end
|
|
||||||
return tc;
|
|
||||||
end
|
|
||||||
|
|
||||||
local function posToStr(pos)
|
local PlayerEnv = dofile(MOD_PATH.."/PlayerEnv.lua");
|
||||||
return "(" .. pos.x .. ", " ..pos.y.. ", " .. pos.z .. ")";
|
|
||||||
|
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
|
end
|
||||||
local posMeta = { __tostring = posToStr };
|
|
||||||
|
|
||||||
minetest.register_privilege(
|
minetest.register_privilege(
|
||||||
"lua",
|
"lua",
|
||||||
|
@ -26,37 +40,22 @@ minetest.register_chatcommand(
|
||||||
description = "Executes a lua statement (chunk), for debugging.",
|
description = "Executes a lua statement (chunk), for debugging.",
|
||||||
privs = { lua = true },
|
privs = { lua = true },
|
||||||
func =
|
func =
|
||||||
function(name, param)
|
function(playerName, paramStr)
|
||||||
local cmdFunc, success, errMsg;
|
local success, errMsg = pcall(runLuaCmd, playerName, paramStr);
|
||||||
|
|
||||||
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);
|
|
||||||
if not success then
|
if not success then
|
||||||
minetest.chat_send_player(name, "ERROR: "..errMsg);
|
minetest.chat_send_player(playerName, "ERROR: "..errMsg);
|
||||||
end
|
end
|
||||||
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