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.lua
master
octacian 2018-07-23 11:48:01 -07:00
parent d749eafb28
commit 642139b1b8
No known key found for this signature in database
GPG Key ID: E84291D11A3509B5
5 changed files with 596 additions and 507 deletions

View File

@ -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)>)`

View File

@ -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 --
----------------------

221
modules/computers/env.lua Normal file
View File

@ -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

222
modules/computers/gui.lua Normal file
View File

@ -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)

View File

@ -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)