-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathenvs.lua
159 lines (136 loc) · 3.84 KB
/
envs.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
local common = ...
local global = _G
local io = io
local math = math
local minetest = minetest
local string = string
local table = table
local chat_send_player = minetest.chat_send_player
local get_player_by_name = minetest.get_player_by_name
local error = error
local find = string.find
local format = string.format
local insert = table.insert
local ipairs = ipairs
local loadfile = loadfile
local log = minetest.log
local pairs = pairs
local setfenv = setfenv -- TODO: polyfill for Lua >= 5.1
local setmetatable = setmetatable
local sort = table.sort
local type = type
local path = minetest.get_modpath(minetest.get_current_modname())
-- for clearing chat window
local bunch_of_lfs = string.rep('\n', 500)
return setmetatable({}, {
__index = function(envs, name)
local player = get_player_by_name(name)
if player == nil then
-- no idea how we could get there, but whatever
log('warning', format('Console attempted to access environment of %s, but there is no such player.', name))
return {}
end
-- variables available for player which cannot be erased
local own = {
me = player,
name = name,
}
--[[
-- disabled because it conflicts with at least one method (get_meta)
local methods = setmetatable({}, {
__index = function(t, k)
if player[k] then
local f = function(...)
return player[k](player, ...)
end
t[k] = f
return f
end
end
})
--]]
-- imports to allow using set_node, sin, write etc.
-- without the need to reference table directly.
-- TODO: optimize access?
local imports = {
own, -- me, name
-- methods, -- getpos(, get_wielded_item(...
common, -- extend(, count(, filter(...
global, -- standard global stuff
string, -- find(, rep(, gmatch(, lower(...
table, -- insert(, remove(, sort(, concat(...
io, -- open(, input(...
math, -- sin(, max(, pi...
minetest, -- set_node(, registered_items, CONTENT_AIR...
}
-- player environment
local env = setmetatable({}, {
-- function for import resolution
__index = function(table, index)
local result
for i, import in ipairs(imports) do
local result = import[index]
if result ~= nil then
return result
end
end
end
})
envs[name] = env
-- Those functions are defined here because more or less
-- they depend on variables in current scope.
-- Returns a table with all keys of given table
-- matching the given pattern. If no table provided,
-- it searches for keys in all imports.
function own.hint(table, pattern)
local result = {}
if pattern == nil then
pattern = table
table = {}
for i, import in ipairs(imports) do
for key, value in pairs(import) do
if find(key, pattern) then
table[key] = value
end
end
end
for key, value in pairs(table) do
insert(result, key)
end
else
if type(table) ~= 'table' then
error('Table expected')
end
for key, value in pairs(table) do
if find(key, pattern) then
insert(result, key)
end
end
end
sort(result)
return result
end
-- Clears the chat window.
function own.clear()
chat_send_player(name, bunch_of_lfs)
end
-- Sends message to player who called it.
function own.echo(s)
chat_send_player(name, s)
end
-- Loads a script into the function with env being the player env
local function load(name)
local result, err = loadfile(path .. '/scripts/' .. name .. '.lua')
if err then
error(err)
end
return setfenv(result, env)
end
own.load = load
-- Runs a script from scripts directory, using load function above
function own.run(name, ...)
return load(name)(...)
end
return env
end,
})