Disconnect player object environment and scripts

Remove the requirement of a player object as a parameter
to make_env and to run_code and run_file. Instead, a
`current_user` meta field is used.
master
octacian 2018-05-31 17:06:15 -07:00
parent 43bc638dbf
commit 7bc3a5c6b1
No known key found for this signature in database
GPG Key ID: E84291D11A3509B5
4 changed files with 98 additions and 53 deletions

View File

@ -22,5 +22,5 @@ read_globals = {
"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",
"refresh", "run", "loadstring", "set_run", "fs",
}

View File

@ -96,7 +96,7 @@ digicompute.c.forms = {
newformname = {
cache_formname = true/false,
get = function(pos, player) ... end,
handle = function(pos, player, fields) ... end,
handle = function(pos, player, fields) ... end,
},
...
}
@ -171,10 +171,10 @@ Deinitializes a computers filesystem. The entry in the computers table is also c
Reinitializes the filesystem of a computer by calling `c:deinit` followed by `c:init`. **Note:** this is destructive and will wipe any files created or changed by the player.
#### `c:on(pos, player)`
**Usage:** `digicompute.c:on(<computer position (table)>, <player (userdata value)>`
#### `c:on(pos)`
**Usage:** `digicompute.c:on(<computer position (table)>)`
Turns a computer on (will not execute if computer is not off). `start.lua` is automatically run, hence the player userdata is required.
Turns a computer on (will not execute if computer is not off). `start.lua` is run upon the next right-click, when the main formspec is launched.
#### `c:off(pos, player)`
**Usage:** `digicompute.c:off(<computer position (table)>, <player (userdata value)>`
@ -189,17 +189,17 @@ Reboots a computer by calling `c:off` followed by `c:on`.
### Environment
This section introduces functions to initialize the environment per-computer and execute a string or file under the environment.
#### `c:make_env(pos, player)`
#### `c:make_env(pos)`
**Usage:** `digicompute.c:make_env(<computer position (table)>, <player (userdata value)>`
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`. The player userdata parameter is required for later callbacks to functions such as `c:open`.
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:run_code(pos, player, code)`
**Usage:** `digicompute.c:run_code(<computer position (table)>, <player (userdata value)>, <code (string)>)`
#### `c:run_code(pos, code)`
**Usage:** `digicompute.c:run_code(<computer position (table)>, <code (string)>)`
Generates an environment table using `c:make_env` and runs the code (provided as third parameter) with `digicompute.run_code` (see `env.md`).
Generates an environment table using `c:make_env` and runs the code (provided as the second parameter) with `digicompute.run_code` (see `env.md`).
#### `c:run_file(pos, player, path)`
#### `c:run_file(pos, path)`
**Usage:** `digicompute.c:run_file(<computer position (table)>, <player (userdata value)>, <path (string)>)`
Generates an environment table using `c:make_env` and runs the code found in the file specified by `path` with `digicompute.run_file` (see `env.md`). **Note:** the path is relative to the computer, meaning that `main.lua` could be run with `digicompute.c:run_file(pos, player, "os/main.lua")`.
Generates an environment table using `c:make_env` and runs the code found in the file specified by `path` with `digicompute.run_file` (see `env.md`). **Note:** the path is relative to the computer, meaning that `main.lua` could be run with `digicompute.c:run_file(pos, "os/main.lua")`.

View File

@ -77,7 +77,7 @@ Stores any piece of information in the non-persistant userdata table. (Table is
#### `refresh()`
**Usage:** `refresh()`
Refresh the computer display, typically after making changes to a buffer, field, or other element.
Refresh the computer display, typically after making changes to a buffer, field, or other element. If `nil` is returned rather than `true`, you have been somehow disconnected from the computer as being the current user (e.g. somebody manually edited the `current_user` meta field); the problem can be solved by simply closing and reopening the formspec manually.
#### `run(code, ...)`
**Usage:** `run(<code (string)>, <additional parameters>)`

View File

@ -8,6 +8,21 @@ 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)
-------------------
-- ID MANAGEMENT --
-------------------
@ -114,6 +129,15 @@ digicompute.c.forms = {
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")
@ -166,7 +190,7 @@ digicompute.c.forms = {
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, player, run)
digicompute.c:run_file(pos, run)
end
end
end,
@ -204,30 +228,39 @@ digicompute.c.forms = {
-- [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 meta:get_string("setup") == "true" then
local meta_formname = meta:get_string("formname")
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
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
formname = "naming"
end
formname = formname or "main"
local form = digicompute.c.forms[formname]
if form then
local name = player:get_player_name()
if form.cache_formname ~= false then
meta:set_string("formname", formname)
end
computer_contexts[name] = minetest.get_meta(pos):get_string("id")
minetest.show_formspec(name, "digicompute:"..formname, form.get(pos, player))
return true
minetest.chat_send_player(name, minetest.colorize("red", "This computer is " ..
"already in use by "..user))
end
end
@ -240,7 +273,13 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if computer then
local pos = computer.pos
minetest.get_meta(pos):set_string("current_user", player:get_player_name())
-- 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!")
@ -275,7 +314,6 @@ function digicompute.c:init(pos)
digicompute.builtin.mkdir(main_path..meta:get_string("owner"))
digicompute.builtin.mkdir(new_path)
digicompute.builtin.cpdir(digicompute.modpath.."/octos/", new_path.."os")
digicompute.c:run_file(pos, meta:get_string("owner"), "os/start.lua")
digicompute.log("Initialized computer "..meta:get_string("id").." owned by "..
meta:get_string("owner").." at "..minetest.pos_to_string(pos))
digicompute.c:infotext(pos)
@ -311,7 +349,7 @@ function digicompute.c:reinit(pos)
end
-- [function] turn computer on
function digicompute.c:on(pos, player)
function digicompute.c:on(pos)
local temp = minetest.get_node(pos)
local ddef = minetest.registered_nodes[temp.name].digicompute
if ddef.state == "off" then
@ -329,10 +367,9 @@ function digicompute.c:on(pos, player)
-- Update infotext
digicompute.c:infotext(pos)
-- Run start if setup
if minetest.get_meta(pos):get_string("setup") == "true" then
digicompute.c:run_file(pos, player, "os/start.lua")
end
-- Set last boot to the current time for later use on_rightclick to
-- check if os/start.lua should be run
minetest.get_meta(pos):set_int("last_boot", os.time())
end, vector.new(pos))
end
end
@ -345,8 +382,10 @@ function digicompute.c:off(pos, player)
minetest.swap_node({x = pos.x, y = pos.y, z = pos.z}, {name = offname, param2 = temp.param2})
-- Update infotext
digicompute.c:infotext(pos)
-- Update Formspec
minetest.close_formspec(player:get_player_name(), "")
-- Close formspec if player object is provided
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", "")
end
@ -354,7 +393,7 @@ end
-- [function] reboot computer
function digicompute.c:reboot(pos, player)
digicompute.c:off(pos, player)
digicompute.c:on(pos, player)
digicompute.c:on(pos)
end
-----------------------
@ -362,7 +401,7 @@ end
-----------------------
-- [function] Make environment
function digicompute.c:make_env(pos, player)
function digicompute.c:make_env(pos)
assert(pos, "digicompute.c:make_env missing position")
local meta = minetest.get_meta(pos)
local cpath = meta:get_string("path")
@ -454,11 +493,17 @@ function digicompute.c:make_env(pos, player)
end
-- [function] refresh
function main.refresh()
return digicompute.c:open(pos, minetest.get_player_by_name(meta:get_string("current_user")))
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, player, 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)
@ -520,7 +565,7 @@ function digicompute.c:make_env(pos, player)
end
-- [function] run file
function fs.run(internal_path, ...)
return digicompute.c:run_file(pos, player, internal_path, ...)
return digicompute.c:run_file(pos, internal_path, ...)
end
-- [function] Settings
function main.Settings(internal_path)
@ -544,16 +589,16 @@ function digicompute.c:make_env(pos, player)
end
-- [function] run code
function digicompute.c:run_code(pos, player, code, ...)
local env = digicompute.c:make_env(pos, player)
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, player, internal_path, ...)
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, player)
local env = digicompute.c:make_env(pos)
local ok, res = digicompute.run_file(complete_path, env, ...)
return ok, res
end
@ -592,7 +637,7 @@ function digicompute.register_computer(itemstring, def)
digicompute.c:infotext(pos)
end,
on_rightclick = function(pos, node, player)
digicompute.c:on(pos, player)
digicompute.c:on(pos)
end,
on_destruct = function(pos)
if minetest.get_meta(pos):get_string("name") then