Prevents write access to box players. Only server privs allow editing boxes outside boxes.
277 lines
7.4 KiB
Lua
277 lines
7.4 KiB
Lua
|
|
--[[
|
|
|
|
terminal - an interactive terminal
|
|
|
|
]]--
|
|
|
|
local context = {}
|
|
|
|
local function get_cmd_params(line)
|
|
local cmd = ""
|
|
local params = ""
|
|
for w in line:gmatch("%w+") do
|
|
if cmd == "" then
|
|
cmd = w
|
|
elseif params == "" then
|
|
params = w
|
|
else
|
|
params = params .. " " .. w
|
|
end
|
|
end
|
|
return cmd, params
|
|
end
|
|
|
|
local help = {
|
|
append = "append text to a file",
|
|
clear = "clear the output",
|
|
echo = "echoes the input back to you",
|
|
help = "display help information for commands",
|
|
list = "list available files",
|
|
lock = "lock the terminal",
|
|
read = "read the content of a file",
|
|
remove = "removes a file",
|
|
unlock = "unlocks the terminal",
|
|
write = "write text to a file",
|
|
}
|
|
|
|
local commands = {
|
|
clear = function(output, params, context)
|
|
return ""
|
|
end,
|
|
append = function(output, params, context)
|
|
if not context.rw then
|
|
return output .. "\nno write access"
|
|
end
|
|
local what, _ = get_cmd_params(params)
|
|
if what == "" then
|
|
return output .. "\nMissing file name"
|
|
end
|
|
context.writing = what
|
|
return output .. "\n" .. "writing \"" .. what .. "\". Enter STOP on a line by itself to finish"
|
|
end,
|
|
write = function(output, params, context)
|
|
if not context.rw then
|
|
return output .. "\nno write access"
|
|
end
|
|
local what, _ = get_cmd_params(params)
|
|
if what == "" then
|
|
return output .. "\nMissing file name"
|
|
end
|
|
context.writing = what
|
|
local meta = minetest.get_meta(context.pos)
|
|
local meta_files = meta:get_string("files")
|
|
if meta_files and meta_files ~= "" then
|
|
local files = minetest.parse_json(meta_files)
|
|
if files[what] then
|
|
files[what] = ""
|
|
meta:set_string("files", minetest.write_json(files))
|
|
end
|
|
end
|
|
return output .. "\n" .. "writing \"" .. what .. "\". Enter STOP on a line by itself to finish"
|
|
end,
|
|
remove = function(output, params, context)
|
|
if not context.rw then
|
|
return output .. "\nno write access"
|
|
end
|
|
local meta = minetest.get_meta(context.pos)
|
|
local meta_files = meta:get_string("files")
|
|
if not meta_files or meta_files == "" then
|
|
return output .. "\nNo such file"
|
|
end
|
|
local files = minetest.parse_json(meta_files)
|
|
local first, _ = get_cmd_params(params)
|
|
if files[first] then
|
|
files[first] = nil
|
|
else
|
|
return output .. "\n" .. "No such file"
|
|
end
|
|
meta:set_string("files", minetest.write_json(files))
|
|
return output .. "\n" .. "removed \"" .. first .. "\""
|
|
end,
|
|
list = function(output, params, context)
|
|
local meta = minetest.get_meta(context.pos)
|
|
local meta_files = meta:get_string("files")
|
|
local files
|
|
if not meta_files or meta_files == "" then
|
|
return output .. "\nNo files found"
|
|
end
|
|
files = minetest.parse_json(meta_files)
|
|
if not files then
|
|
return output .. "\nNo files found"
|
|
end
|
|
for k, _ in pairs(files) do
|
|
output = output .. "\n" .. k
|
|
end
|
|
return output
|
|
end,
|
|
echo = function(output, params, context)
|
|
return output .. "\n" .. params
|
|
end,
|
|
read = function(output, params, context)
|
|
local meta = minetest.get_meta(context.pos)
|
|
local meta_files = meta:get_string("files")
|
|
if not meta_files or meta_files == "" then
|
|
return output .. "\nNo such file"
|
|
end
|
|
local files = minetest.parse_json(meta_files)
|
|
local first, _ = get_cmd_params(params)
|
|
if files[first] then
|
|
return output .. "\n" .. files[first]
|
|
else
|
|
return output .. "\n" .. "No such file"
|
|
end
|
|
return output
|
|
end,
|
|
lock = function(output, params, context)
|
|
local meta = minetest.get_meta(context.pos)
|
|
meta:set_int("locked", 1)
|
|
return output .. "\n" .. "terminal locked"
|
|
end,
|
|
unlock = function(output, params, context)
|
|
return output .. "\n" .. "unable to connect to authentication service"
|
|
end,
|
|
help = function(output, params, context)
|
|
if params ~= "" then
|
|
local h, _ = get_cmd_params(params)
|
|
if help[h] then
|
|
return output .. "\n" .. help[h]
|
|
else
|
|
return output .. "\nno help for \"" .. h .. "\""
|
|
end
|
|
end
|
|
return output .. "\n" ..
|
|
"append clear echo help list lock read remove unlock write"
|
|
end,
|
|
}
|
|
|
|
local function make_formspec(output, prompt)
|
|
local f =
|
|
"size[12,8]" ..
|
|
"field_close_on_enter[input;false]" ..
|
|
"textlist[0.4,0.5;11,6;output;"
|
|
|
|
local c = 1
|
|
for part in output:gmatch("[^\r\n]+") do
|
|
f = f .. minetest.formspec_escape(part) .. ","
|
|
c = c + 1
|
|
end
|
|
f = f .. minetest.formspec_escape(prompt) .. ";" .. c .. ";false]"
|
|
|
|
f = f .. "field[0.7,7;11.2,1;input;;]"
|
|
return f
|
|
end
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname ~= "terminal:" then
|
|
return false
|
|
end
|
|
local line = fields.input
|
|
if line and line ~= "" then
|
|
local name = player:get_player_name()
|
|
local c = context[name]
|
|
local output = c.output or ""
|
|
|
|
if c.writing then
|
|
-- this shouldn't get reached, but just to be safe, check ro
|
|
if not context.rw then
|
|
c.writing = nil
|
|
output = output .. "\n" .. line
|
|
output = output .. "\nno write access"
|
|
c.output = output
|
|
minetest.show_formspec(name, "terminal:", make_formspec(output, "> "))
|
|
return true
|
|
end
|
|
-- are we writing a file?
|
|
if line == "STOP" then
|
|
-- done writing a file
|
|
c.writing = nil
|
|
output = output .. "\n" .. line
|
|
c.output = output
|
|
minetest.show_formspec(name, "terminal:", make_formspec(output, "> "))
|
|
return true
|
|
end
|
|
local meta = minetest.get_meta(c.pos)
|
|
local meta_files = meta:get_string("files")
|
|
local files = {}
|
|
if not meta_files or meta_files == "" then
|
|
files[c.writing] = line
|
|
else
|
|
files = minetest.parse_json(meta_files)
|
|
if not files[c.writing] then
|
|
files[c.writing] = line
|
|
else
|
|
files[c.writing] = files[c.writing] .. "\n" .. line
|
|
end
|
|
end
|
|
meta:set_string("files", minetest.write_json(files))
|
|
output = output .. "\n" .. line
|
|
c.output = output
|
|
minetest.show_formspec(name, "terminal:", make_formspec(output, ""))
|
|
else
|
|
-- else parse cmd
|
|
output = output .. "\n> " .. line
|
|
|
|
local meta = minetest.get_meta(c.pos)
|
|
local cmd, params = get_cmd_params(line)
|
|
if meta:get_int("locked") == 1 and cmd ~= "unlock" then
|
|
output = output .. "\nTerminal locked, type \"unlock\" to unlock it"
|
|
c.output = output
|
|
minetest.show_formspec(name, "terminal:", make_formspec(output, "> "))
|
|
return true
|
|
end
|
|
|
|
local fn = commands[cmd]
|
|
if fn then
|
|
output = fn(output, params, c)
|
|
else
|
|
output = output .. "\n" .. "Syntax Error"
|
|
end
|
|
c.output = output
|
|
minetest.show_formspec(name, "terminal:", make_formspec(output, "> "))
|
|
end
|
|
end
|
|
return true
|
|
end)
|
|
|
|
local terminal_use = function(pos, node, clicker, itemstack, pointed_thing)
|
|
if not clicker then
|
|
return
|
|
end
|
|
local name = clicker:get_player_name()
|
|
context[name] = {
|
|
pos = pos,
|
|
rw = false,
|
|
output = "",
|
|
}
|
|
if boxes.players_editing_boxes[name] or
|
|
(not boxes.players_in_boxes[name] and minetest.check_player_privs(clicker, "server")) then
|
|
-- allow rw access
|
|
context[name].rw = true
|
|
end
|
|
-- send formspec to player
|
|
minetest.show_formspec(name, "terminal:", make_formspec("", "> "))
|
|
end
|
|
|
|
|
|
minetest.register_node("terminal:terminal", {
|
|
description = "An interactive terminal console emulator access interface unit controller",
|
|
drawtype = "mesh",
|
|
mesh = "terminal.obj",
|
|
tiles = {
|
|
{name = "terminal_base.png"},
|
|
{name = "terminal_idle.png", animation = {type = "vertical_frames", aspect_w = 14, aspect_h = 13, length = 4.0}},
|
|
},
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
on_trigger = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_int("locked", 0)
|
|
end,
|
|
on_untrigger = function(pos)
|
|
local meta = minetest.get_meta(pos)
|
|
meta:set_int("locked", 1)
|
|
end,
|
|
on_rightclick = terminal_use,
|
|
})
|