datamine/init.lua

154 lines
4.0 KiB
Lua
Raw Permalink Normal View History

2016-11-11 23:47:47 -08:00
local LIB_PATH = "preempter.so"
2016-11-13 01:46:56 -08:00
local MAX_FILE_SIZE = 100000
local MAX_MEMORY = 1024
2016-11-13 01:49:13 -08:00
datamine = {}
2016-11-13 01:46:56 -08:00
local modpath = minetest.get_modpath(minetest.get_current_modname()) .. "/"
2016-11-13 01:49:13 -08:00
datamine.modpath = modpath
2016-11-11 23:47:47 -08:00
local insecure_env = minetest.request_insecure_environment()
if not insecure_env then
2016-11-13 01:49:13 -08:00
local err = "[datamine] This mod requires an insecure environment to run.\n"
2016-11-13 01:46:56 -08:00
err = err .. "Please add this mod as a trusted mod, or disable mod security."
error(err)
2016-11-11 23:47:47 -08:00
end
2016-11-13 01:49:13 -08:00
datamine.sandboxed_resume =
assert(insecure_env.package.loadlib(modpath .. LIB_PATH, "sandboxed_resume"))
2016-11-11 23:47:47 -08:00
2016-11-13 01:46:56 -08:00
local Computer = dofile(modpath .. "computer.lua")
local Buffer = dofile(modpath .. "buffer.lua")
local os_file = assert(io.open(modpath .. "os.lua", "r"))
local os_source = os_file:read("*all")
os_file:close()
local function env()
return {
yield = coroutine.yield,
table = {
concat = table.concat,
insert = table.insert,
},
Buffer = Buffer,
ipairs = ipairs,
pairs = pairs,
string = {
sub = string.sub
},
tostring = tostring,
error = error,
2016-11-13 01:46:56 -08:00
}
end
local function caps(cpu, mem)
return { cpu = cpu, memory = mem }
end
local function os_program()
local program = assert(loadstring(os_source))
2016-11-13 01:46:56 -08:00
setfenv(program, env())
return program
end
-- Screen formspecs
2016-11-13 01:49:13 -08:00
function datamine.screen_formspec(display)
2016-11-13 01:46:56 -08:00
local everything = {}
everything[1] = "size[8,8]textarea[0,0;8,7;output;;"
everything[2] = minetest.formspec_escape(display)
everything[3] = "]field[0,7;6,1;input;;]button[7,7;1,1;submit;>]"
return table.concat(everything)
end
local hash_pos = minetest.hash_node_position
local unhash_pos = minetest.get_position_from_hash
-- Map from position hashes to computers
local active_computers = {}
local function run_computers()
local remove_these = {}
for poshash, computer in pairs(active_computers) do
local pos = unhash_pos(poshash)
local node = minetest.get_node_or_nil(pos)
2016-11-13 01:49:13 -08:00
if node and node.name == "datamine:computer" then
2016-11-13 01:46:56 -08:00
computer:run(pos)
if computer.state ~= "on" then
table.insert(remove_these, poshash)
end
else
table.insert(remove_these, poshash)
end
end
for i, poshash in ipairs(remove_these) do
active_computers[poshash] = nil
end
end
minetest.register_globalstep(run_computers)
local function add_computer(pos, computer)
active_computers[hash_pos(pos)] = computer
end
local function start_computer(pos, meta)
local computer = Computer.new(env(), caps(1000, MAX_MEMORY), os_program())
add_computer(pos, computer)
return computer
end
2016-11-13 01:49:13 -08:00
function datamine.get_computer(pos)
2016-11-13 01:46:56 -08:00
return active_computers[hash_pos(pos)]
end
2016-11-11 23:47:47 -08:00
2016-11-13 01:46:56 -08:00
-- Computer Nodes
2016-11-13 01:49:13 -08:00
minetest.register_node("datamine:computer", {
2016-11-13 01:46:56 -08:00
description = "Computer",
groups = { cracky = 3 },
drawtype = "normal",
2016-11-13 15:14:14 -08:00
paramtype2 = "facedir",
tiles = {
"datamine_computer_blank.png",
"datamine_computer_blank.png",
"datamine_computer_blank.png",
"datamine_computer_left.png",
"datamine_computer_blank.png",
"datamine_computer_front.png",
},
2016-11-13 01:46:56 -08:00
after_place_node = function(pos, placer, itemstack, pointed_thing)
local p_name = placer and placer:get_player_name() or ""
local meta = minetest.get_meta(pos)
meta:set_string("owner", p_name)
2016-11-13 01:49:13 -08:00
meta:set_string("formspec", datamine.screen_formspec(""))
2016-11-13 01:46:56 -08:00
meta:set_string("used_space", 0)
meta:set_string("max_space", MAX_FILE_SIZE)
start_computer(pos, meta)
end,
on_receive_fields = function(pos, formname, fields, sender)
2016-11-13 01:49:13 -08:00
local computer = datamine.get_computer(pos)
2016-11-13 01:46:56 -08:00
if not computer then
computer = start_computer(pos, minetest.get_meta(pos))
elseif fields.submit and fields.input then
for s in string.gmatch(fields.input, "([^\n]+)\n?") do
computer:interrupt("text", s)
end
local meta = minetest.get_meta(pos)
2016-11-13 01:49:13 -08:00
meta:set_string("formspec", datamine.screen_formspec(fields.output or ""))
2016-11-13 01:46:56 -08:00
end
end,
digiline = {
receptor = {},
effector = {
action = function(pos, node, channel, msg)
local computer = datamine.get_computer(pos)
if computer then
computer:interrupt("digiline", {
channel = channel,
data = msg,
})
end
end,
},
}
2016-11-13 01:46:56 -08:00
})