4 ITB (insidethebox) minetest game - Copyright (C) 2017-2018 sofar & nore
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public License
8 as published by the Free Software Foundation; either version 2.1
9 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 terminal - an interactive terminal
31 local function get_cmd_params(line
)
34 for w
in line
:gmatch("%w+") do
37 elseif params
== "" then
40 params
= params
.. " " .. w
47 append
= "append text to a file",
48 clear
= "clear the output",
49 echo
= "echoes the input back to you",
50 help
= "display help information for commands",
51 list
= "list available files",
52 lock
= "lock the terminal",
53 read = "read the content of a file",
54 remove = "removes a file",
55 unlock
= "unlocks the terminal",
56 write = "write text to a file",
57 edit
= "edits a file in an editor",
60 local function make_formspec(output
, prompt
)
63 "field_close_on_enter[input;false]" ..
64 "textlist[0.4,0.5;11,6;output;"
67 for part
in output
:gmatch("[^\r\n]+") do
68 f
= f
.. minetest
.formspec_escape(part
) .. ","
71 f
= f
.. minetest
.formspec_escape(prompt
) .. ";" .. c
.. ";false]"
73 f
= f
.. "field[0.7,7;11.2,1;input;;]"
78 clear
= function(output
, params
, c
)
81 append
= function(output
, params
, c
)
83 return output
.. "\nError: No write access"
85 local what
, _
= get_cmd_params(params
)
87 return output
.. "\nError: Missing file name"
90 return output
.. "\nWriting \"" .. what
.. "\". Enter STOP on a line by itself to finish"
92 write = function(output
, params
, c
)
94 return output
.. "\nError: No write access"
96 local what
, _
= get_cmd_params(params
)
98 return output
.. "\nError: Missing file name"
101 local meta
= minetest
.get_meta(c
.pos
)
102 local meta_files
= meta
:get_string("files")
103 if meta_files
and meta_files
~= "" then
104 local files
= minetest
.parse_json(meta_files
) or {}
105 if files
and files
[what
] then
107 meta
:set_string("files", minetest
.write_json(files
))
108 meta
:mark_as_private("files")
111 return output
.. "\nWriting \"" .. what
.. "\". Enter STOP on a line by itself to finish"
113 edit
= function(output
, params
, c
)
115 return output
.. "\nError: No write access"
117 local what
, _
= get_cmd_params(params
)
119 return output
.. "\nError: Missing file name"
125 local meta
= minetest
.get_meta(c
.pos
)
126 local meta_files
= meta
:get_string("files")
127 if meta_files
and meta_files
~= "" then
128 local files
= minetest
.parse_json(meta_files
) or {}
129 if files
and files
[what
] then
134 fsc
.show(c
.name
, "size[12,8]" ..
135 "textarea[0.5,0.5;11.5,7.0;text;text;" ..
136 minetest
.formspec_escape(text
) .. "]" ..
137 "button_exit[5.2,7.2;1.6,0.5;exit;Save]",
143 remove = function(output
, params
, c
)
145 return output
.. "\nError: No write access"
147 local meta
= minetest
.get_meta(c
.pos
)
148 local meta_files
= meta
:get_string("files")
149 if not meta_files
or meta_files
== "" then
150 return output
.. "\nError: No such file"
152 local files
= minetest
.parse_json(meta_files
) or {}
153 local first
, _
= get_cmd_params(params
)
157 return output
.. "\nError: No such file"
159 meta
:set_string("files", minetest
.write_json(files
))
160 meta
:mark_as_private("files")
161 return output
.. "\nRemoved \"" .. first
.. "\""
163 list
= function(output
, params
, c
)
164 local meta
= minetest
.get_meta(c
.pos
)
165 local meta_files
= meta
:get_string("files")
167 if not meta_files
or meta_files
== "" then
168 return output
.. "\nError: No files found"
170 files
= minetest
.parse_json(meta_files
) or {}
172 return output
.. "\nError: No files found"
174 for k
, _
in pairs(files
) do
175 output
= output
.. "\n" .. k
179 echo
= function(output
, params
, c
)
180 return output
.. "\n" .. params
182 read = function(output
, params
, c
)
183 local meta
= minetest
.get_meta(c
.pos
)
184 local meta_files
= meta
:get_string("files")
185 if not meta_files
or meta_files
== "" then
186 return output
.. "\nError: No such file"
188 local files
= minetest
.parse_json(meta_files
) or {}
189 local first
, _
= get_cmd_params(params
)
191 if first
== "rules" then
192 rules
.show(c
.name
, "player")
195 return output
.. "\n" .. files
[first
]
197 return output
.. "\nError: No such file"
200 lock
= function(output
, params
, c
)
202 return output
.. "\nError: no write access"
204 local meta
= minetest
.get_meta(c
.pos
)
205 meta
:set_int("locked", 1)
206 meta
:mark_as_private("locked")
207 return output
.. "\n" .. "Terminal locked"
209 unlock
= function(output
, params
, c
)
210 return output
.. "\n" .. "Error: unable to connect to authentication service"
212 help
= function(output
, params
, c
)
214 local h
, _
= get_cmd_params(params
)
216 return output
.. "\n" .. term
.help
[h
]
218 return output
.. "\nError: No help for \"" .. h
.. "\""
223 for k
, _
in pairs(term
.help
) do
227 for _
, v
in ipairs(ot
) do
228 o
= o
.. " " .. v
.. "\n"
230 return output
.. "\n" ..
231 "Available commands:\n" ..
233 "Type `help <command>` for more help about that command"
237 function term
.recv(player
, fields
, context
)
239 local name
= player
:get_player_name()
241 if not c
or not c
.pos
then
242 log.fs_data(player
, name
, "terminal:", fields
)
246 local line
= fields
.input
247 if line
and line
~= "" then
248 local output
= c
.output
or ""
249 minetest
.sound_play("terminal_keyboard_clicks", {pos
= c
.pos
})
252 -- this shouldn't get reached, but just to be safe, check ro
255 output
= output
.. "\n" .. line
256 output
= output
.. "\nError: no write access"
259 make_formspec(output
, "> "),
264 -- are we writing a file?
265 if line
== "STOP" then
266 -- done writing a file
268 output
= output
.. "\n" .. line
271 make_formspec(output
, "> "),
276 local meta
= minetest
.get_meta(c
.pos
)
277 local meta_files
= meta
:get_string("files")
279 if not meta_files
or meta_files
== "" then
280 files
[c
.writing
] = line
282 files
= minetest
.parse_json(meta_files
) or {}
283 if not files
[c
.writing
] then
284 files
[c
.writing
] = line
286 files
[c
.writing
] = files
[c
.writing
] .. "\n" .. line
289 if string.len(files
[c
.writing
]) < 16384 then
290 local json
= minetest
.write_json(files
)
291 if string.len(json
) < 49152 then
292 meta
:set_string("files", json
)
293 meta
:mark_as_private("files")
294 output
= output
.. "\n" .. line
296 output
= output
.. "\n" .. "Error: no space left on device"
299 output
= output
.. "\n" .. "Error: maximum file length exceeded"
303 make_formspec(output
, ""),
309 output
= output
.. "\n> " .. line
311 local meta
= minetest
.get_meta(c
.pos
)
312 local cmd
, params
= get_cmd_params(line
)
313 if meta
:get_int("locked") == 1 and cmd
~= "unlock" then
314 output
= output
.. "\nError: Terminal locked, type \"unlock\" to unlock it"
317 make_formspec(output
, "> "),
323 local fn
= term
.commands
[cmd
]
325 output
= fn(output
, params
, c
)
327 output
= output
.. "\n" .. "Error: Syntax Error. Try \"help\""
329 if output
~= false then
332 make_formspec(output
, "> "),
338 elseif fields
.quit
then
339 minetest
.sound_play("terminal_power_off", {pos
= c
.pos
})
341 elseif fields
.output
then
342 -- CHG events - do not return true
346 log.fs_data(player
, name
, "terminal:", fields
)
350 function term
.edit(player
, fields
, context
)
351 if not fields
.text
then
355 local name
= player
:get_player_name()
357 if not c
or not c
.pos
or not c
.output
then
358 log.fs_data(player
, name
, "terminal:", fields
)
361 local output
= c
.output
364 output
= output
.. "\n" .. "Error: no such file\n"
366 make_formspec(output
, "> "),
372 local meta
= minetest
.get_meta(c
.pos
)
373 local meta_files
= meta
:get_string("files")
375 files
= minetest
.parse_json(meta_files
) or {}
376 files
[c
.what
] = fields
.text
379 local json
= minetest
.write_json(files
)
380 if string.len(json
) < 49152 then
381 meta
:set_string("files", json
)
382 meta
:mark_as_private("files")
383 output
= output
.. "\n" .. "Wrote: " .. c
.what
.. "\n"
385 output
= output
.. "\n" .. "Error: no space left on device\n"
389 make_formspec(output
, "> "),
395 local terminal_use
= function(pos
, node
, clicker
, itemstack
, pointed_thing
)
399 local name
= clicker
:get_player_name()
406 if boxes
.players_editing_boxes
[name
] or
407 (not boxes
.players_in_boxes
[name
] and minetest
.check_player_privs(clicker
, "server")) then
411 -- send formspec to player
413 make_formspec("", "> "),
416 minetest
.sound_play("terminal_power_on", {pos
= pos
})
417 -- trigger on first use
418 local meta
= minetest
.get_meta(pos
)
419 if meta
:get_int("locked") ~= 1 then
421 minetest
.after(1.0, mech
.untrigger
, pos
)
425 minetest
.register_node("terminal:terminal", {
426 description
= "An interactive terminal console emulator access interface unit controller",
428 mesh
= "terminal.obj",
429 groups
= {mech
= 1, trigger
= 1},
431 {name
= "terminal_base.png"},
432 {name
= "terminal_idle.png", animation
= {type = "vertical_frames", aspect_w
= 14, aspect_h
= 13, length
= 4.0}},
435 paramtype2
= "facedir",
436 on_trigger
= function(pos
)
437 local meta
= minetest
.get_meta(pos
)
438 minetest
.sound_play("terminal_power_on", {pos
= pos
})
439 meta
:set_int("locked", 0)
440 meta
:mark_as_private("locked")
442 on_untrigger
= function(pos
)
443 local meta
= minetest
.get_meta(pos
)
444 minetest
.sound_play("terminal_power_off", {pos
= pos
})
445 meta
:set_int("locked", 1)
446 meta
:mark_as_private("locked")
448 on_rightclick
= terminal_use
,