Preserve, improve environment and replace userdata

* Preserve the environment table so that it must
only be regenerated after a game restart, after
a computer is restarted, and at the tiem of the
initialization of a computer.
* Replace the current meta-based userdata
mechanisms with a global `ram` variable within the
environment, as the preservation of the environment
itself causes its global variables to be preserved
as well
* Make `get_attr` convert meta to a table before
accessing the requested key in order to ensure that
the meta can be correctly accessed even if it is
not a string
* Initialize output_editable meta on node place
master
octacian 2018-06-01 07:21:44 -07:00
parent fdeb68a5d5
commit d749eafb28
No known key found for this signature in database
GPG Key ID: E84291D11A3509B5
7 changed files with 57 additions and 45 deletions

View File

@ -5,6 +5,9 @@ globals = {
"minetest",
"jit",
"digicompute",
-- OctOS Internals
"ram",
}
read_globals = {
@ -21,6 +24,6 @@ read_globals = {
-- OctOS Internals (custom environment functions)
"set_help", "get_attr", "get_output", "set_output",
"set_output_editable", "get_input", "set_input",
"get_os", "set_os", "get_userdata", "set_userdata",
"refresh", "run", "loadstring", "set_run", "fs",
"get_os", "set_os", "refresh", "run", "loadstring",
"set_run", "fs",
}

View File

@ -1,6 +1,10 @@
# OctOS
OctOS is the operating system used by digicomputers. OctOS is made of many Linux-like commands which are documented in `commands.md`, however, there is also an API which can be used when writing programs for OctOS. The API can be used by players to interact with the computer under a safe and secure environment. The documentation is divided into two sections as is the code, main (for general functions), and filesystem (for filesystem access).
## Accessing the RAM (userdata)
In earlier versions of digicompute, a RAM-like storage mechanism could be accessed with a `get_userdata` and `set_userdata` API. However, this API was later removed and instead the RAM is accessed by setting values of the `ram` table within the environment. Data can also be preserved by setting a global variable within the environment, however, use of the `ram` table is recommended. This is because of how digicompute handles the environments in the background. Global variables, including the `ram` table, are stored within the environment itself, and with the environment being preserved until the computer is shut off or deinitialized, the variables are preserved as well. Please note that digicompute does not currently have a completely accurate representation of RAM, in that there is no limitation to the amount of data that can be stored.
## Main
This contains a set of functions mainly for the purpose of interacting with the computer's displays.
@ -23,6 +27,9 @@ Gets a piece of global information from the node meta (storage). Several common
* `input`: input field.
* `output`: output buffer.
* `name`: computer name.
* `help`: formspec help text.
* `id`: computer id.
* `output_editable`: whether the output buffer is editable.
#### `get_output()`
**Usage:** `get_output()`
@ -64,16 +71,6 @@ Sets a piece of information stored in the OS table. This table stores basic valu
* `reboot`: command to reboot the computer.
* `prefix`: prefix printed at the beginning of a new line.
#### `get_userdata(key)`
**Usage:** `get_userdata(<data name (string)>)`
Gets a piece of information from the userdata table. This table is like RAM, as information will be reset when the computer is turned off.
#### `set_userdata(key, value)`
**Usage:** `set_userdata(<data name (string)>, <value>`
Stores any piece of information in the non-persistant userdata table. (Table is cleared when computer is turned off, therefore non-persistant.)
#### `refresh()`
**Usage:** `refresh()`

View File

@ -5,6 +5,8 @@ digicompute.c = {}
local path = digicompute.path
local main_path = path.."computers/"
local environments = {}
-- Make computer directory
digicompute.builtin.mkdir(main_path)
@ -374,8 +376,13 @@ function digicompute.c:deinit(pos, clear_entry)
end
end
local id = meta:get_string("id")
-- Remove saved environment
if environments[id] then
environments[id] = nil
end
if clear_entry ~= false then
local id = meta:get_string("id")
computers[id] = nil
end
end
@ -429,6 +436,7 @@ end
function digicompute.c:off(pos, player)
local temp = minetest.get_node(pos) -- Get basic node information
local offname = "digicompute:"..minetest.registered_nodes[temp.name].digicompute.base
local meta = minetest.get_meta(pos)
-- Swap node to off
minetest.swap_node({x = pos.x, y = pos.y, z = pos.z}, {name = offname, param2 = temp.param2})
-- Update infotext
@ -437,8 +445,13 @@ function digicompute.c:off(pos, player)
if player and player.get_player_name then
minetest.close_formspec(player:get_player_name(), "")
end
-- Clear update buffer
minetest.get_meta(pos):set_string("output", "")
-- Clear output buffer
meta:set_string("output", "")
-- Reset environment
local id = meta:get_string("id")
if environments[id] then
environments[id] = nil
end
end
-- [function] reboot computer
@ -455,6 +468,13 @@ end
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
@ -484,7 +504,7 @@ function digicompute.c:make_env(pos)
end
-- [function] get attribute
function main.get_attr(key)
return meta:get_string(key) or nil
return meta:to_table().fields[key] or nil
end
-- [function] get output
function main.get_output()
@ -531,17 +551,6 @@ function digicompute.c:make_env(pos)
return false
end
end
-- [function] get userdata value
function main.get_userdata(key)
local res = meta:get_string("userdata")
return minetest.deserialize(res)[key] or nil
end
-- [function] set userdata value
function main.set_userdata(key, value)
local table = minetest.deserialize(meta:get_string("userdata")) or {}
table[key] = value
return meta:set_string("userdata", minetest.serialize(table))
end
-- [function] refresh
function main.refresh()
local current_user = meta:get_string("current_user")
@ -636,7 +645,10 @@ function digicompute.c:make_env(pos)
env[k] = v
end
return env
env.ram = {} -- RAM table, replacement for userdata
environments[id] = env
return environments[id]
end
-- [function] run code
@ -680,8 +692,8 @@ function digicompute.register_computer(itemstring, def)
meta:set_string("input", "") -- Initialize input buffer
meta:set_string("output", "") -- Initialize output buffer
meta:set_string("os", "") -- Initialize OS table
meta:set_string("userdata", "") -- Initialize userdata table
meta:set_string("help", "Type a command and press enter.") -- Initialize help
meta:set_string("output_editable", "false") -- Initialize uneditable output
digicompute.c:new_id(pos) -- Set up ID
-- Update infotext

View File

@ -1,8 +1,8 @@
-- cmd: help --
local params = ...
local bin = get_userdata("bin")
local param = params[1]
local bin = ram.bin
--[local function] Sort the help list alphabetically
local function sort(list)

View File

@ -1,24 +1,24 @@
if get_attr("run") == "os/exec/nano.lua" then
local input = get_attr("input")
if input == "save" then
fs.write(get_userdata("nano:path"), get_output(), "w")
fs.write(ram.nano_path, get_output(), "w")
elseif input == "discard" or input == "exit" then
if input == "exit" then
fs.write(get_userdata("nano:path"), get_output(), "w")
fs.write(ram.nano_path, get_output(), "w")
end
set_userdata("nano:path", nil) -- Clear nano path
set_os("prefix", get_userdata("nano:prefix")) -- Restore prefix
set_userdata("nano:prefix", nil) -- Clear stored prefix
set_output(get_userdata("nano:output").."\n"..get_os("prefix")) -- Restore output
set_userdata("nano:output", nil) -- Clear stored output
ram.nano_path = nil -- Clear nano path
set_os("prefix", ram.nano_prefix) -- Restore prefix
ram.nano_prefix = nil -- Clear stored prefix
set_output(ram.nano_output.."\n"..get_os("prefix")) -- Restore output
ram.nano_output = nil -- Clear stored output
set_run() -- Clear custom run file
-- Restore "output editable" to previous state
if not get_userdata("nano:output_was_editable") then
if not ram.nano_output_was_editable then
set_output_editable(false)
else
set_userdata("nano:output_was_editable", nil)
ram.nano_output_was_editable = nil
end
end
@ -31,10 +31,10 @@ else
if path then
local contents = fs.read(path) or ""
set_userdata("nano:path", path) -- Store editing path for later
set_userdata("nano:output", get_output()) -- Store old output for later
ram.nano_path = path -- Store editing path for later
ram.nano_output = get_output() -- Store old output for later
set_output(contents) -- Set output to contents of file or blank
set_userdata("nano:prefix", get_os("prefix")) -- Store OS prefix for later
ram.nano_prefix = get_os("prefix") -- Store OS prefix for later
set_os("prefix", "") -- Set OS prefix to a blank string
set_help("\"save\" to save, \"discard\" to discard and exit, \"exit\" to save and exit") -- Add information to help
set_run("os/exec/nano.lua") -- Set run file to the nano executable
@ -43,7 +43,7 @@ else
if get_attr("output_editable") == "false" then
set_output_editable(true)
else
set_userdata("nano:output_was_editable", "true")
ram.nano_output_was_editable = true
end
refresh() -- Refresh formspec

View File

@ -1,5 +1,5 @@
local input = get_attr("input"):split(" ")
local bin = get_userdata("bin")
local bin = ram.bin
if input[1] ~= "" then
print(get_attr("input"), false)

View File

@ -27,7 +27,7 @@ bin[get_os("off")] = { description = "Turn off computer" } -- Turn off computer
bin[get_os("reboot")] = { description = "Reboot computer" } -- Reboot computer
-- Save bin table
set_userdata("bin", bin)
ram.bin = bin
-- Set initial output value
set_output("Welcome to octOS version 0.2.\n\n"..get_os("prefix")) -- print welcome