Split API into different files
* Move formspec APIs to gui.lua * Move environment APIs to env.lua * Move userdata and computer ID APIs to init.luamaster
parent
d749eafb28
commit
642139b1b8
|
@ -59,6 +59,19 @@ Above is example code from the default computer. Computers should typically be r
|
|||
## Advanced API
|
||||
This API is more of a documentation of pre-existing API functions for developers new to this mod who would like to get started. The Advanced API documentation is sectioned out as it is in the code.
|
||||
|
||||
### Current User Management
|
||||
This section manages the temporary data that represents the different players interacting with computers.
|
||||
|
||||
#### `c:set_user(pos, name)`
|
||||
**Usage:** `digicompute.c:set_user(<computer position (table)>, <player username (string)>)`
|
||||
|
||||
Set the current user of the computer at the position specified. If there is an existing user, it will be overridden and the formspec shown to the previous user will be closed.
|
||||
|
||||
#### `c:unset_user(pos, name)`
|
||||
**Usage:** `digicompute.c:unset_user(<computer position (table)>, <player username (string)>)`
|
||||
|
||||
Unset the current user of the computer at the position specified and close the formspec open to the player.
|
||||
|
||||
### ID Management
|
||||
This section manages loading, saving, and assigning new IDs to computers.
|
||||
|
||||
|
@ -148,8 +161,8 @@ The `cache_formname` field is used in `digicompute.c:open` to choose whether or
|
|||
|
||||
Shows a form defined in the forms table. If the formname is not provided, it will be set to the formname cached in meta (if any), and default to `main`. Fields are automatically sent to the `handle` function defined in the forms table. **Note:** `player` should not be the a plaintext string containing the player name, but a userdata value.
|
||||
|
||||
### Helper Functions
|
||||
This section defines several helper functions used in the formspecs, environment, and node definition.
|
||||
### Computer Operations
|
||||
This section defines several functions that handle computer operations, such as initialization and booting.
|
||||
|
||||
#### `c:infotext(pos)`
|
||||
**Usage:** `digicompute.c:infotext(<computer position (table)>)`
|
||||
|
@ -199,6 +212,16 @@ This section introduces functions to initialize the environment per-computer and
|
|||
|
||||
Returns a table of functions allowed under the environment. The table is made up of a wide array of functions for interacting with the computer and its file system. These are joined with the table returned by `digicompute.env()`, explaned in `env.md`.
|
||||
|
||||
#### `c:get_env(pos)`
|
||||
**Usage:** `digicompute.c:get_env(<computer position (table)>)`
|
||||
|
||||
Get a previously created environment based upon the position of the computer for which it was created. Returns the complete environment table should it exist.
|
||||
|
||||
#### `c:remove_env(pos)`
|
||||
**Usage:** `digicompute.c:remove_env(<computer position (table)>)`
|
||||
|
||||
Remove a previously created environment based upon the position of the computer for which it was created. Always returns `true`.
|
||||
|
||||
#### `c:run_code(pos, code)`
|
||||
**Usage:** `digicompute.c:run_code(<computer position (table)>, <code (string)>)`
|
||||
|
||||
|
|
|
@ -1,79 +1,9 @@
|
|||
-- computers/api.lua
|
||||
|
||||
digicompute.c = {}
|
||||
|
||||
local path = digicompute.path
|
||||
local main_path = path.."computers/"
|
||||
|
||||
local environments = {}
|
||||
|
||||
-- Make computer directory
|
||||
digicompute.builtin.mkdir(main_path)
|
||||
|
||||
-----------------------------
|
||||
-- CURRENT USER MANAGEMENT --
|
||||
-----------------------------
|
||||
|
||||
local current_users = {}
|
||||
|
||||
-- [event] remove current users on leave
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if current_users[name] then
|
||||
minetest.get_meta(current_users[name]):set_string("current_user", nil)
|
||||
current_users[name] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
-------------------
|
||||
-- ID MANAGEMENT --
|
||||
-------------------
|
||||
|
||||
local computers = {}
|
||||
|
||||
-- [function] load computers
|
||||
function digicompute.load_computers()
|
||||
local res = digicompute.builtin.read(path.."/computers.txt")
|
||||
if res then
|
||||
res = minetest.deserialize(res)
|
||||
if type(res) == "table" then
|
||||
computers = res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Load all computers
|
||||
digicompute.load_computers()
|
||||
|
||||
-- [function] save computers
|
||||
function digicompute.save_computers()
|
||||
digicompute.builtin.write(path.."/computers.txt", minetest.serialize(computers))
|
||||
end
|
||||
|
||||
-- [function] generate new computer ID
|
||||
function digicompute.c:new_id(pos)
|
||||
assert(type(pos) == "table", "digicompute.c:new_id requires a valid position")
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local function count()
|
||||
local c = 1
|
||||
for _, i in pairs(computers) do
|
||||
c = c + 1
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
local id = "c_"..count()
|
||||
|
||||
computers[id] = {
|
||||
pos = pos,
|
||||
}
|
||||
|
||||
meta:set_string("id", id)
|
||||
end
|
||||
|
||||
-- [event] save computers on shutdown
|
||||
minetest.register_on_shutdown(digicompute.save_computers)
|
||||
local computers = digicompute.loaded_computers
|
||||
|
||||
----------------------------------
|
||||
-- MID-BOOT COMPUTER MANAGEMENT --
|
||||
|
@ -109,227 +39,9 @@ minetest.after(0, function()
|
|||
coroutine.resume(check_booting)
|
||||
end)
|
||||
|
||||
-------------------
|
||||
---- FORMSPECS ----
|
||||
-------------------
|
||||
|
||||
local computer_contexts = {}
|
||||
|
||||
local tabs = {
|
||||
"main",
|
||||
"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")).."]"..
|
||||
"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 =
|
||||
"tableoptions[background=#000000FF;highlight=#00000000;border=false]"..
|
||||
"table[-0.25,-0.38;10.38,11.17;list_credits;"..table.concat(output, ",")..";"..#output.."]"
|
||||
end
|
||||
|
||||
return
|
||||
"size[10,11]"..
|
||||
"tabheader[0,0;tabs;Command Line,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
|
||||
local os = minetest.deserialize(meta:get_string("os")) or {}
|
||||
local prefix = os.prefix or ""
|
||||
|
||||
if fields.input or fields.key_enter_field == "name" then
|
||||
if fields.input == os.clear then
|
||||
meta:set_string("output", prefix)
|
||||
meta:set_string("input", "")
|
||||
digicompute.c:open(pos, player)
|
||||
elseif fields.input == os.off then digicompute.c:off(pos, player)
|
||||
elseif fields.input == os.reboot then digicompute.c:reboot(pos, player)
|
||||
else -- else, turn over to os
|
||||
-- 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
|
||||
end,
|
||||
},
|
||||
settings = {
|
||||
get = function(pos)
|
||||
return
|
||||
"size[10,11]"..
|
||||
"tabheader[0,0;tabs;Command Line,Settings;2]"..
|
||||
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.]"..
|
||||
"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 <theoctacian@gmail.com>]"
|
||||
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")
|
||||
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
|
||||
|
||||
-- Add current user
|
||||
meta:set_string("current_user", name)
|
||||
current_users[name] = pos
|
||||
|
||||
computer_contexts[name] = minetest.get_meta(pos):get_string("id")
|
||||
minetest.show_formspec(name, "digicompute:"..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(":")
|
||||
|
||||
if formname[1] == "digicompute" and digicompute.c.forms[formname[2]] then
|
||||
local computer = computers[computer_contexts[player:get_player_name()]]
|
||||
|
||||
if computer then
|
||||
local pos = computer.pos
|
||||
|
||||
-- if formspec quit, remove current user
|
||||
if fields.quit == "true" then
|
||||
minetest.get_meta(pos):set_string("current_user", nil)
|
||||
current_users[player:get_player_name()] = nil
|
||||
end
|
||||
|
||||
digicompute.c.forms[formname[2]].handle(pos, player, fields)
|
||||
else
|
||||
minetest.chat_send_player(player:get_player_name(), "Computer could not be found!")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
----------------------
|
||||
-- HELPER FUNCTIONS --
|
||||
----------------------
|
||||
-------------------------
|
||||
-- COMPUTER OPERATIONS --
|
||||
-------------------------
|
||||
|
||||
-- [function] update infotext
|
||||
function digicompute.c:infotext(pos)
|
||||
|
@ -378,9 +90,7 @@ function digicompute.c:deinit(pos, clear_entry)
|
|||
|
||||
local id = meta:get_string("id")
|
||||
-- Remove saved environment
|
||||
if environments[id] then
|
||||
environments[id] = nil
|
||||
end
|
||||
digicompute.c:remove_env(pos)
|
||||
|
||||
if clear_entry ~= false then
|
||||
computers[id] = nil
|
||||
|
@ -448,10 +158,7 @@ function digicompute.c:off(pos, player)
|
|||
-- Clear output buffer
|
||||
meta:set_string("output", "")
|
||||
-- Reset environment
|
||||
local id = meta:get_string("id")
|
||||
if environments[id] then
|
||||
environments[id] = nil
|
||||
end
|
||||
digicompute.c:remove_env(pos)
|
||||
end
|
||||
|
||||
-- [function] reboot computer
|
||||
|
@ -460,212 +167,6 @@ function digicompute.c:reboot(pos, player)
|
|||
digicompute.c:on(pos)
|
||||
end
|
||||
|
||||
-----------------------
|
||||
----- ENVIRONMENT -----
|
||||
-----------------------
|
||||
|
||||
-- [function] Make environment
|
||||
function digicompute.c:make_env(pos)
|
||||
assert(pos, "digicompute.c:make_env missing position")
|
||||
local meta = minetest.get_meta(pos)
|
||||
local id = meta:get_string("id")
|
||||
|
||||
-- if an environment for this computer has already been generated, return it instead
|
||||
if environments[id] then
|
||||
return environments[id]
|
||||
end
|
||||
|
||||
local cpath = meta:get_string("path")
|
||||
|
||||
-- Main Environment Functions
|
||||
|
||||
local main = {}
|
||||
|
||||
-- [function] print
|
||||
function main.print(contents, newline)
|
||||
if type(contents) ~= "string" then
|
||||
contents = dump(contents)
|
||||
end
|
||||
if newline == false then
|
||||
newline = ""
|
||||
else
|
||||
newline = "\n"
|
||||
end
|
||||
|
||||
meta:set_string("output", meta:get_string("output")..newline..contents)
|
||||
end
|
||||
-- [function] set help
|
||||
function main.set_help(value)
|
||||
if not value or type(value) ~= "string" then
|
||||
value = "Type a command and press enter."
|
||||
end
|
||||
|
||||
return meta:set_string("help", value)
|
||||
end
|
||||
-- [function] get attribute
|
||||
function main.get_attr(key)
|
||||
return meta:to_table().fields[key] or nil
|
||||
end
|
||||
-- [function] get output
|
||||
function main.get_output()
|
||||
return meta:get_string("output") or nil
|
||||
end
|
||||
-- [function] set output
|
||||
function main.set_output(value)
|
||||
return meta:set_string("output", value)
|
||||
end
|
||||
-- [function] set whether output is writable
|
||||
function main.set_output_editable(bool)
|
||||
if bool == true then
|
||||
meta:set_string("output_editable", "true")
|
||||
else
|
||||
meta:set_string("output_editable", "false")
|
||||
end
|
||||
end
|
||||
-- [function] get input
|
||||
function main.get_input()
|
||||
return meta:get_string("input") or nil
|
||||
end
|
||||
-- [function] set input
|
||||
function main.set_input(value)
|
||||
return meta:set_string("input", value)
|
||||
end
|
||||
-- [function] get os value
|
||||
function main.get_os(key)
|
||||
return minetest.deserialize(meta:get_string("os"))[key] or nil
|
||||
end
|
||||
-- [function] set os value
|
||||
function main.set_os(key, value)
|
||||
local allowed_keys = {
|
||||
clear = true,
|
||||
off = true,
|
||||
reboot = true,
|
||||
prefix = true,
|
||||
}
|
||||
|
||||
if allowed_keys[key] == true then
|
||||
local table = minetest.deserialize(meta:get_string("os")) or {}
|
||||
table[key] = value
|
||||
return meta:set_string("os", minetest.serialize(table))
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- [function] refresh
|
||||
function main.refresh()
|
||||
local current_user = meta:get_string("current_user")
|
||||
if current_user ~= "" then
|
||||
local player = minetest.get_player_by_name(current_user)
|
||||
if player then
|
||||
return digicompute.c:open(pos, player)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- [function] run code
|
||||
function main.run(code, ...)
|
||||
return digicompute.c:run_code(pos, code, ...)
|
||||
end
|
||||
-- [function] set file to be run when input is submitted
|
||||
function main.set_run(run_path)
|
||||
if run_path then
|
||||
if digicompute.builtin.exists(cpath..run_path) then
|
||||
meta:set_string("run", run_path)
|
||||
end
|
||||
else
|
||||
meta:set_string("run", "os/main.lua")
|
||||
end
|
||||
end
|
||||
|
||||
-- Filesystem Environment Functions
|
||||
|
||||
local fs = {}
|
||||
|
||||
-- [function] exists
|
||||
function fs.exists(internal_path)
|
||||
return digicompute.builtin.exists(cpath..internal_path)
|
||||
end
|
||||
-- [function] create file
|
||||
function fs.create(internal_path)
|
||||
return digicompute.builtin.create(cpath..internal_path)
|
||||
end
|
||||
-- [function] remove file
|
||||
function fs.remove(internal_path)
|
||||
return os.remove(cpath..internal_path)
|
||||
end
|
||||
-- [function] write to file
|
||||
function fs.write(internal_path, data, mode)
|
||||
if type(data) ~= "string" then
|
||||
data = dump(data)
|
||||
end
|
||||
return digicompute.builtin.write(cpath..internal_path, data, mode)
|
||||
end
|
||||
-- [function] read file
|
||||
function fs.read(internal_path)
|
||||
return digicompute.builtin.read(cpath..internal_path)
|
||||
end
|
||||
-- [function] list directory contents
|
||||
function fs.list(internal_path)
|
||||
return digicompute.builtin.list(cpath..internal_path)
|
||||
end
|
||||
-- [function] copy file
|
||||
function fs.copy(original, new)
|
||||
return digicompute.builtin.copy(cpath..original, cpath..new)
|
||||
end
|
||||
-- [function] create directory
|
||||
function fs.mkdir(internal_path)
|
||||
return digicompute.builtin.mkdir(cpath..internal_path)
|
||||
end
|
||||
-- [function] remove directory
|
||||
function fs.rmdir(internal_path)
|
||||
return digicompute.builtin.rmdir(cpath..internal_path)
|
||||
end
|
||||
-- [function] copy directory
|
||||
function fs.cpdir(original, new)
|
||||
return digicompute.builtin.cpdir(cpath..original, cpath..new)
|
||||
end
|
||||
-- [function] run file
|
||||
function fs.run(internal_path, ...)
|
||||
return digicompute.c:run_file(pos, internal_path, ...)
|
||||
end
|
||||
-- [function] Settings
|
||||
function main.Settings(internal_path)
|
||||
local fpath = cpath..internal_path
|
||||
if digicompute.builtin.exists(fpath) then
|
||||
return Settings(fpath)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get default env table
|
||||
|
||||
local env = digicompute.env()
|
||||
|
||||
env.fs = fs
|
||||
|
||||
for k, v in pairs(main) do
|
||||
env[k] = v
|
||||
end
|
||||
|
||||
env.ram = {} -- RAM table, replacement for userdata
|
||||
|
||||
environments[id] = env
|
||||
return environments[id]
|
||||
end
|
||||
|
||||
-- [function] run code
|
||||
function digicompute.c:run_code(pos, code, ...)
|
||||
local env = digicompute.c:make_env(pos)
|
||||
local ok, res = digicompute.run_code(code, env, ...)
|
||||
return ok, res
|
||||
end
|
||||
|
||||
-- [function] run file
|
||||
function digicompute.c:run_file(pos, internal_path, ...)
|
||||
local complete_path = minetest.get_meta(pos):get_string("path")..internal_path
|
||||
local env = digicompute.c:make_env(pos)
|
||||
local ok, res = digicompute.run_file(complete_path, env, ...)
|
||||
return ok, res
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- NODE DEFINITIONS --
|
||||
----------------------
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
-- computers/env.lua
|
||||
|
||||
local environments = {}
|
||||
|
||||
-----------------------
|
||||
----- ENVIRONMENT -----
|
||||
-----------------------
|
||||
|
||||
-- [function] Make environment
|
||||
function digicompute.c:make_env(pos)
|
||||
assert(pos, "digicompute.c:make_env missing position")
|
||||
local meta = minetest.get_meta(pos)
|
||||
local id = meta:get_string("id")
|
||||
|
||||
-- if an environment for this computer has already been generated, return it instead
|
||||
if environments[id] then
|
||||
return environments[id]
|
||||
end
|
||||
|
||||
local cpath = meta:get_string("path")
|
||||
|
||||
-- Main Environment Functions
|
||||
|
||||
local main = {}
|
||||
|
||||
-- [function] print
|
||||
function main.print(contents, newline)
|
||||
if type(contents) ~= "string" then
|
||||
contents = dump(contents)
|
||||
end
|
||||
if newline == false then
|
||||
newline = ""
|
||||
else
|
||||
newline = "\n"
|
||||
end
|
||||
|
||||
meta:set_string("output", meta:get_string("output")..newline..contents)
|
||||
end
|
||||
-- [function] set help
|
||||
function main.set_help(value)
|
||||
if not value or type(value) ~= "string" then
|
||||
value = "Type a command and press enter."
|
||||
end
|
||||
|
||||
return meta:set_string("help", value)
|
||||
end
|
||||
-- [function] get attribute
|
||||
function main.get_attr(key)
|
||||
return meta:to_table().fields[key] or nil
|
||||
end
|
||||
-- [function] get output
|
||||
function main.get_output()
|
||||
return meta:get_string("output") or nil
|
||||
end
|
||||
-- [function] set output
|
||||
function main.set_output(value)
|
||||
return meta:set_string("output", value)
|
||||
end
|
||||
-- [function] set whether output is writable
|
||||
function main.set_output_editable(bool)
|
||||
if bool == true then
|
||||
meta:set_string("output_editable", "true")
|
||||
else
|
||||
meta:set_string("output_editable", "false")
|
||||
end
|
||||
end
|
||||
-- [function] get input
|
||||
function main.get_input()
|
||||
return meta:get_string("input") or nil
|
||||
end
|
||||
-- [function] set input
|
||||
function main.set_input(value)
|
||||
return meta:set_string("input", value)
|
||||
end
|
||||
-- [function] get os value
|
||||
function main.get_os(key)
|
||||
return minetest.deserialize(meta:get_string("os"))[key] or nil
|
||||
end
|
||||
-- [function] set os value
|
||||
function main.set_os(key, value)
|
||||
local allowed_keys = {
|
||||
clear = true,
|
||||
off = true,
|
||||
reboot = true,
|
||||
prefix = true,
|
||||
}
|
||||
|
||||
if allowed_keys[key] == true then
|
||||
local table = minetest.deserialize(meta:get_string("os")) or {}
|
||||
table[key] = value
|
||||
return meta:set_string("os", minetest.serialize(table))
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- [function] refresh
|
||||
function main.refresh()
|
||||
local current_user = meta:get_string("current_user")
|
||||
if current_user ~= "" then
|
||||
local player = minetest.get_player_by_name(current_user)
|
||||
if player then
|
||||
return digicompute.c:open(pos, player)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- [function] run code
|
||||
function main.run(code, ...)
|
||||
return digicompute.c:run_code(pos, code, ...)
|
||||
end
|
||||
-- [function] set file to be run when input is submitted
|
||||
function main.set_run(run_path)
|
||||
if run_path then
|
||||
if digicompute.builtin.exists(cpath..run_path) then
|
||||
meta:set_string("run", run_path)
|
||||
end
|
||||
else
|
||||
meta:set_string("run", "os/main.lua")
|
||||
end
|
||||
end
|
||||
|
||||
-- Filesystem Environment Functions
|
||||
|
||||
local fs = {}
|
||||
|
||||
-- [function] exists
|
||||
function fs.exists(internal_path)
|
||||
return digicompute.builtin.exists(cpath..internal_path)
|
||||
end
|
||||
-- [function] create file
|
||||
function fs.create(internal_path)
|
||||
return digicompute.builtin.create(cpath..internal_path)
|
||||
end
|
||||
-- [function] remove file
|
||||
function fs.remove(internal_path)
|
||||
return os.remove(cpath..internal_path)
|
||||
end
|
||||
-- [function] write to file
|
||||
function fs.write(internal_path, data, mode)
|
||||
if type(data) ~= "string" then
|
||||
data = dump(data)
|
||||
end
|
||||
return digicompute.builtin.write(cpath..internal_path, data, mode)
|
||||
end
|
||||
-- [function] read file
|
||||
function fs.read(internal_path)
|
||||
return digicompute.builtin.read(cpath..internal_path)
|
||||
end
|
||||
-- [function] list directory contents
|
||||
function fs.list(internal_path)
|
||||
return digicompute.builtin.list(cpath..internal_path)
|
||||
end
|
||||
-- [function] copy file
|
||||
function fs.copy(original, new)
|
||||
return digicompute.builtin.copy(cpath..original, cpath..new)
|
||||
end
|
||||
-- [function] create directory
|
||||
function fs.mkdir(internal_path)
|
||||
return digicompute.builtin.mkdir(cpath..internal_path)
|
||||
end
|
||||
-- [function] remove directory
|
||||
function fs.rmdir(internal_path)
|
||||
return digicompute.builtin.rmdir(cpath..internal_path)
|
||||
end
|
||||
-- [function] copy directory
|
||||
function fs.cpdir(original, new)
|
||||
return digicompute.builtin.cpdir(cpath..original, cpath..new)
|
||||
end
|
||||
-- [function] run file
|
||||
function fs.run(internal_path, ...)
|
||||
return digicompute.c:run_file(pos, internal_path, ...)
|
||||
end
|
||||
-- [function] Settings
|
||||
function main.Settings(internal_path)
|
||||
local fpath = cpath..internal_path
|
||||
if digicompute.builtin.exists(fpath) then
|
||||
return Settings(fpath)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get default env table
|
||||
|
||||
local env = digicompute.env()
|
||||
|
||||
env.fs = fs
|
||||
|
||||
for k, v in pairs(main) do
|
||||
env[k] = v
|
||||
end
|
||||
|
||||
env.ram = {} -- RAM table, replacement for userdata
|
||||
|
||||
environments[id] = env
|
||||
return environments[id]
|
||||
end
|
||||
|
||||
-- [function] Get environment
|
||||
function digicompute.c:get_env(pos)
|
||||
local id = minetest.get_meta(pos):get_string("id")
|
||||
return environments[id]
|
||||
end
|
||||
|
||||
-- [function] Remove environment
|
||||
function digicompute.c:remove_env(pos)
|
||||
environments[minetest.get_meta(pos):get_string("id")] = nil
|
||||
return true
|
||||
end
|
||||
|
||||
-- [function] run code
|
||||
function digicompute.c:run_code(pos, code, ...)
|
||||
local env = digicompute.c:make_env(pos)
|
||||
local ok, res = digicompute.run_code(code, env, ...)
|
||||
return ok, res
|
||||
end
|
||||
|
||||
-- [function] run file
|
||||
function digicompute.c:run_file(pos, internal_path, ...)
|
||||
local complete_path = minetest.get_meta(pos):get_string("path")..internal_path
|
||||
local env = digicompute.c:make_env(pos)
|
||||
local ok, res = digicompute.run_file(complete_path, env, ...)
|
||||
return ok, res
|
||||
end
|
|
@ -0,0 +1,222 @@
|
|||
-- computers/gui.lua
|
||||
|
||||
local path = digicompute.path
|
||||
local main_path = path.."computers/"
|
||||
|
||||
local computers = digicompute.loaded_computers
|
||||
|
||||
-------------------
|
||||
---- FORMSPECS ----
|
||||
-------------------
|
||||
|
||||
local computer_contexts = {}
|
||||
|
||||
local tabs = {
|
||||
"main",
|
||||
"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")).."]"..
|
||||
"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 =
|
||||
"tableoptions[background=#000000FF;highlight=#00000000;border=false]"..
|
||||
"table[-0.25,-0.38;10.38,11.17;list_credits;"..table.concat(output, ",")..";"..#output.."]"
|
||||
end
|
||||
|
||||
return
|
||||
"size[10,11]"..
|
||||
"tabheader[0,0;tabs;Command Line,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
|
||||
local os = minetest.deserialize(meta:get_string("os")) or {}
|
||||
local prefix = os.prefix or ""
|
||||
|
||||
if fields.input or fields.key_enter_field == "name" then
|
||||
if fields.input == os.clear then
|
||||
meta:set_string("output", prefix)
|
||||
meta:set_string("input", "")
|
||||
digicompute.c:open(pos, player)
|
||||
elseif fields.input == os.off then digicompute.c:off(pos, player)
|
||||
elseif fields.input == os.reboot then digicompute.c:reboot(pos, player)
|
||||
else -- else, turn over to os
|
||||
-- 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
|
||||
end,
|
||||
},
|
||||
settings = {
|
||||
get = function(pos)
|
||||
return
|
||||
"size[10,11]"..
|
||||
"tabheader[0,0;tabs;Command Line,Settings;2]"..
|
||||
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.]"..
|
||||
"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 <theoctacian@gmail.com>]"
|
||||
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")
|
||||
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:"..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(":")
|
||||
|
||||
if formname[1] == "digicompute" and digicompute.c.forms[formname[2]] then
|
||||
local computer = computers[computer_contexts[player:get_player_name()]]
|
||||
|
||||
if computer then
|
||||
local pos = computer.pos
|
||||
|
||||
-- if formspec quit, remove current user
|
||||
if fields.quit == "true" then
|
||||
digicompute.c:unset_user(pos, player:get_player_name())
|
||||
end
|
||||
|
||||
digicompute.c.forms[formname[2]].handle(pos, player, fields)
|
||||
else
|
||||
minetest.chat_send_player(player:get_player_name(), "Computer could not be found!")
|
||||
end
|
||||
end
|
||||
end)
|
|
@ -1,7 +1,129 @@
|
|||
-- computers/init.lua
|
||||
|
||||
digicompute.c = {}
|
||||
|
||||
local path = digicompute.path
|
||||
local main_path = path.."computers/"
|
||||
-- Make computer directory
|
||||
digicompute.builtin.mkdir(main_path)
|
||||
|
||||
-----------------------------
|
||||
-- CURRENT USER MANAGEMENT --
|
||||
-----------------------------
|
||||
|
||||
local current_users = {}
|
||||
|
||||
-- [event] remove current users on leave
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if current_users[name] then
|
||||
minetest.get_meta(current_users[name]):set_string("current_user", nil)
|
||||
current_users[name] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
-- [function] Set current user
|
||||
function digicompute.c:set_user(pos, name)
|
||||
current_users[name] = pos
|
||||
|
||||
local meta = minetest.get_meta(current_users[name])
|
||||
local current_user = meta:get_string("current_user")
|
||||
-- Check if there was already another user
|
||||
if current_user ~= "" then
|
||||
if minetest.get_player_by_name(current_user) then
|
||||
local formname = meta:get_string("formname")
|
||||
-- if formname is defined, close that formspec
|
||||
if formname ~= "" then
|
||||
minetest.close_formspec(current_user, "digicompute:"..formname)
|
||||
else -- else, just close everything
|
||||
minetest.close_formspec(current_user)
|
||||
end
|
||||
-- Remove from current users
|
||||
current_users[current_user] = nil
|
||||
end
|
||||
end
|
||||
-- Update node meta entry
|
||||
meta:set_string("current_user", name)
|
||||
end
|
||||
|
||||
-- [function] Unset current user
|
||||
function digicompute.c:unset_user(pos, name)
|
||||
local meta = minetest.get_meta(current_users[name])
|
||||
-- Clear node meta entry
|
||||
meta:set_string("current_user", nil)
|
||||
current_users[name] = nil -- Remove from table
|
||||
|
||||
local formname = meta:get_string("formname")
|
||||
-- if formname is defined, close that formspec
|
||||
if formname ~= "" then
|
||||
minetest.close_formspec(name, "digicompute:"..formname)
|
||||
else -- else, just close everything
|
||||
minetest.close_formspec(name)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- ID MANAGEMENT --
|
||||
-------------------
|
||||
|
||||
local computers = {}
|
||||
|
||||
-- [function] load computers
|
||||
function digicompute.load_computers()
|
||||
local res = digicompute.builtin.read(path.."/computers.txt")
|
||||
if res then
|
||||
res = minetest.deserialize(res)
|
||||
if type(res) == "table" then
|
||||
computers = res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Load all computers
|
||||
digicompute.load_computers()
|
||||
|
||||
-- [function] save computers
|
||||
function digicompute.save_computers()
|
||||
digicompute.builtin.write(path.."/computers.txt", minetest.serialize(computers))
|
||||
end
|
||||
|
||||
-- [function] generate new computer ID
|
||||
function digicompute.c:new_id(pos)
|
||||
assert(type(pos) == "table", "digicompute.c:new_id requires a valid position")
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local function count()
|
||||
local c = 1
|
||||
for _, i in pairs(computers) do
|
||||
c = c + 1
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
local id = "c_"..count()
|
||||
|
||||
computers[id] = {
|
||||
pos = pos,
|
||||
}
|
||||
|
||||
meta:set_string("id", id)
|
||||
end
|
||||
|
||||
-- [event] save computers on shutdown
|
||||
minetest.register_on_shutdown(digicompute.save_computers)
|
||||
|
||||
digicompute.loaded_computers = computers
|
||||
|
||||
-----------------------------
|
||||
-- Load External Resources --
|
||||
-----------------------------
|
||||
|
||||
local module_path = digicompute.get_module_path("computers")
|
||||
|
||||
-- Load env
|
||||
dofile(module_path.."/env.lua")
|
||||
-- Load GUI
|
||||
dofile(module_path.."/gui.lua")
|
||||
-- Load API
|
||||
dofile(module_path.."/api.lua")
|
||||
-- Load nodes (computers)
|
||||
|
|
Loading…
Reference in New Issue