-- computers/gui.lua local path = digicompute.path local main_path = path.."computers/" local computers = digicompute.loaded_computers -- [local function] Wrap text inserting a comma after a line exceeds the limit local function prepare_text(str, limit) if type(str) == "string" then local res = "" local newline = false local line_length = 0 for c in str:gmatch(".") do -- if newline is true, wait for a space or 10 extra characters to insert a newline if newline then if c == " " or (line_length - limit) > 10 then res = res .. "," newline = false line_length = 0 else res = res .. c line_length = line_length + 1 end -- elseif character is an unescaped break, reset line length elseif c == "," and res:sub(-1) ~= "\\" then line_length = 0 newline = false res = res .. c -- else, increment line length else line_length = line_length + 1 -- if line is too long, set to break at next space if line_length > limit then newline = true end res = res .. c end end return res end end ------------------- ---- FORMSPECS ---- ------------------- local computer_contexts = {} local tabs = { "main", "debug", "settings", } -- [function] handle tabs function digicompute.c:handle_tabs(pos, player, fields) if fields.tabs then if digicompute.c:open(pos, player, tabs[tonumber(fields.tabs)]) then return true end end end digicompute.c.forms = { naming = { cache_formname = false, get = function(pos) local meta = minetest.get_meta(pos) return "size[6,1.7]".. default.gui_bg_img.. "field[.25,0.50;6,1;name;Computer Name:;"..minetest.formspec_escape(meta:get_string("name")).."]".. "field_close_on_enter[name;false]".. "button[4.95,1;1,1;submit_name;Set]" end, handle = function(pos, player, fields) local meta = minetest.get_meta(pos) local name = player:get_player_name() local owner = meta:get_string("owner") if owner == name then if fields.name or fields.key_enter_field == "name" and fields.name ~= "" then meta:set_string("name", fields.name) meta:set_string("setup", "true") meta:set_string("path", main_path..meta:get_string("owner").."/"..meta:get_string("id").."/") meta:set_string("run", "os/main.lua") -- Set default run file digicompute.c:init(pos) digicompute.c:open(pos, player) else minetest.chat_send_player(name, "Name cannot be empty.") end else minetest.chat_send_player(name, "Only the owner can set this computer. ("..owner..")") end end, }, main = { get = function(pos) local meta = minetest.get_meta(pos) local last_start = meta:get_int("last_run_start") if last_start == 0 or last_start < meta:get_int("last_boot") then if meta:get_string("setup") == "true" then meta:set_int("last_run_start", os.time()) digicompute.c:run_file(pos, "os/start.lua") end end local input = minetest.formspec_escape(meta:get_string("input")) local help = minetest.formspec_escape(meta:get_string("help")) local output = meta:get_string("output") if meta:get_string("output_editable") == "true" then output = minetest.formspec_escape(output) output = "textarea[-0.03,-0.4;10.62,13.03;output;;"..output.."]" else output = output:split("\n", true) for i, line in ipairs(output) do output[i] = minetest.formspec_escape(line) end output = prepare_text(table.concat(output, ","), meta:get_int("wrap_limit")) output = "tableoptions[background=#000000FF;highlight=#00000000;border=false]".. "table[-0.25,-0.38;10.38,11.17;list_credits;"..output..";"..#output.."]" end return "size[10,11]".. "tabheader[0,0;tabs;Command Line,Debug Console,Settings;1]".. "bgcolor[#000000FF;]".. output.. "button[9.56,10.22;0.8,2;help;?]".. "tooltip[help;"..help.."]".. "field[-0.02,10.99;10.1,1;input;;"..input.."]".. "field_close_on_enter[input;false]" end, handle = function(pos, player, fields) if digicompute.c:handle_tabs(pos, player, fields) then return end local meta = minetest.get_meta(pos) -- get meta -- Hand values over to operating system if fields.input or fields.key_enter_field == "name" then -- Set meta value(s) meta:set_string("input", fields.input) if fields.output then meta:set_string("output", fields.output) end local run = meta:get_string("run") if run == "" then run = "os/main.lua" end -- Get and run current "run file" (default: os/main.lua) digicompute.c:run_file(pos, run) end end, }, debug = { get = function(pos) local meta = minetest.get_meta(pos) local debug = minetest.deserialize(meta:get_string("debug")) local length = 0 -- Escape lines for _, l in pairs(debug) do debug[_] = minetest.formspec_escape(l) length = length + 1 end -- Concatenate and wrap debug = prepare_text(table.concat(debug, ","), meta:get_int("wrap_limit")) return "size[10,11]".. "tabheader[0,0;tabs;Command Line,Debug Console,Settings;2]".. default.gui_bg_img.. "tableoptions[background=#000000FF;highlight=#00000000;border=false]".. "table[-0.25,-0.38;10.38,11.17;debug;"..debug..";"..length.."]".. "button[-0.28,10.22;10.6,2;clear;Clear Debug Console]" end, handle = function(pos, player, fields) if digicompute.c:handle_tabs(pos, player, fields) then return end if fields.clear then local meta = minetest.get_meta(pos) meta:set_string("debug", minetest.serialize({})) -- Clear debug buffer digicompute.c:open(pos, player) -- Refresh formspec end end, }, settings = { get = function(pos) local meta = minetest.get_meta(pos) local limit = tostring(meta:get_int("wrap_limit")) local wrap_msg = "Wrap text after (default: 90; min: 10):" wrap_msg = minetest.formspec_escape(wrap_msg) return "size[10,11]".. "tabheader[0,0;tabs;Command Line,Debug Console,Settings;3]".. default.gui_bg_img.. "button[0.5,0.25;9,1;reset;Reset Filesystem]".. "tooltip[reset;Wipes all files and OS data replacing it with the basic octOS.]".. "field[0.8,1.7;7,1;wrap_limit;"..wrap_msg..";"..limit.."]".. "field_close_on_enter[wrap_limit;false]".. "tooltip[wrap_limit;Number of characters after which to wrap text.]".. "button[7.5,1.4;1,1;wrap_save;Save]".. "tooltip[wrap_save;Save wrap limit]".. "button[8.5,1.4;1,1;wrap_reset;Reset]".. "tooltip[wrap_reset;Reset wrap limit to default]".. "label[0.5,10.35;digicompute Version: "..tostring(digicompute.VERSION)..", ".. digicompute.RELEASE_TYPE.."]".. "label[0.5,10.75;(c) Copywrite "..tostring(os.date("%Y")).." ".. "Elijah Duffy ]" end, handle = function(pos, player, fields) if digicompute.c:handle_tabs(pos, player, fields) then return end local meta = minetest.get_meta(pos) if fields.reset then -- Clear buffers meta:set_string("output", "") meta:set_string("input", "") -- Reset Filesystem digicompute.c:reinit(pos) -- Rerun start.lua meta:set_int("last_run_start", os.time()) digicompute.c:run_file(pos, "os/start.lua") elseif fields.key_enter_field == "wrap_limit" or fields.wrap_save then if fields.wrap_limit == "" then digicompute.c:open(pos, player) else local new_limit = tonumber(fields.wrap_limit) if new_limit and new_limit >= 10 then meta:set_int("wrap_limit", new_limit) digicompute.c:print_debug(pos, "Set wrap limit to "..new_limit) else digicompute.c:open(pos, player) end end elseif fields.wrap_reset then meta:set_int("wrap_limit", 90) digicompute.c:print_debug(pos, "Reset wrap limit to 90") digicompute.c:open(pos, player) end end, }, } -- [function] open formspec function digicompute.c:open(pos, player, formname) local meta = minetest.get_meta(pos) local user = meta:get_string("current_user") local name = player:get_player_name() if user == "" or user == name then if meta:get_string("setup") == "true" then local meta_formname = meta:get_string("formname") if not formname and meta_formname and meta_formname ~= "" then formname = meta_formname end else formname = "naming" end formname = formname or "main" local form = digicompute.c.forms[formname] if form then if form.cache_formname ~= false then meta:set_string("formname", formname) end -- Set current user digicompute.c:set_user(pos, name) computer_contexts[name] = minetest.get_meta(pos):get_string("id") minetest.show_formspec(name, "digicompute_redo:"..formname, form.get(pos, player)) return true end else minetest.chat_send_player(name, minetest.colorize("red", "This computer is " .. "already in use by "..user)) end end -- [event] on receive fields minetest.register_on_player_receive_fields(function(player, formname, fields) formname = formname:split(":") local name = player:get_player_name() if formname[1] == "digicompute" and digicompute.c.forms[formname[2]] then local computer = computers[computer_contexts[name]] if computer then local pos = computer.pos local meta = minetest.get_meta(pos) -- if formspec quit, remove current user if fields.quit == "true" then digicompute.c:unset_user(pos, name) end -- if input is from the current user, process if name == meta:get_string("current_user") then digicompute.c.forms[formname[2]].handle(pos, player, fields) elseif not fields.quit then -- elseif not already closed, close formspec minetest.close_formspec(name, formname) end else minetest.chat_send_player(player:get_player_name(), "Computer could not be found!") end end end)