2021-05-03 13:02:39 +08:00

280 lines
8.7 KiB
Lua

-- computers/api.lua
local path = digicompute.path
local main_path = path.."computers/"
local computers = digicompute.loaded_computers
----------------------------------
-- MID-BOOT COMPUTER MANAGEMENT --
----------------------------------
-- Loop through all computers in a coroutine and check if
-- any were left in the midst of the boot process
local check_booting = coroutine.create(function()
-- [function] Get node
local function get_node(pos)
local node = minetest.get_node_or_nil(pos)
if node then return node end
minetest.get_voxel_manip(pos, pos)
return minetest.get_node(pos)
end
for id, c in pairs(computers) do
if c.booting then
local temp = get_node(c.pos)
local ddef = minetest.registered_nodes[temp.name].digicompute
if ddef.state == "off" or ddef.state == "bios" then
local name, param2 = "digicompute_redo:"..ddef.base, temp.param2
digicompute.c:complete_boot(c.pos, id, name, param2)
else
c.booting = nil
end
end
end
end)
-- Start coroutine
minetest.after(0, function()
coroutine.resume(check_booting)
end)
-------------------------
-- COMPUTER OPERATIONS --
-------------------------
-- [function] update infotext
function digicompute.c:infotext(pos)
local meta = minetest.get_meta(pos)
local state = minetest.registered_nodes[minetest.get_node(pos).name].digicompute.state
if meta:get_string("setup") == "true" then
meta:set_string("infotext", meta:get_string("name").." - "..state.."\n(owned by "
..meta:get_string("owner")..")")
else
meta:set_string("infotext", "Unconfigured Computer - "..state.."\n(owned by "
..meta:get_string("owner")..")")
end
end
-- [function] print to computer debug buffer
function digicompute.c:print_debug(pos, msg)
if type(msg) ~= "string" then msg = dump(msg) end
local meta = minetest.get_meta(pos)
local debug = minetest.deserialize(meta:get_string("debug"))
table.insert(debug, os.date("[%d/%m/%Y @ %H:%M] ")..msg)
meta:set_string("debug", minetest.serialize(debug))
return true
end
-- [function] initialize computer
function digicompute.c:init(pos)
local meta = minetest.get_meta(pos)
local new_path = meta:get_string("path")
if new_path and new_path ~= "" then
digicompute.builtin.mkdir(main_path..meta:get_string("owner"))
digicompute.builtin.mkdir(new_path)
digicompute.builtin.cpdir(digicompute.modpath.."/octos/", new_path.."os")
digicompute.log("Initialized computer "..meta:get_string("id").." owned by "..
meta:get_string("owner").." at "..minetest.pos_to_string(pos))
digicompute.c:infotext(pos)
digicompute.c:print_debug(pos, "Initialized")
end
end
-- [function] deinitialize computer
function digicompute.c:deinit(pos, clear_entry)
local meta = minetest.get_meta(pos)
local old_path = meta:get_string("path")
local owner = meta:get_string("owner")
if old_path and old_path ~= "" then
digicompute.builtin.rmdir(old_path)
digicompute.log("Deinitialized computer "..meta:get_string("id").." owned by "..
meta:get_string("owner").." at "..minetest.pos_to_string(pos))
if digicompute.builtin.list(main_path..owner).subdirs then
digicompute.builtin.rmdir(main_path..owner)
end
end
local id = meta:get_string("id")
-- Remove saved environment
digicompute.c:remove_env(pos)
if clear_entry ~= false then
computers[id] = nil
end
end
-- [function] reinitialize computer (reset)
function digicompute.c:reinit(pos)
digicompute.c:deinit(pos, false)
digicompute.c:init(pos)
end
-- [function] complete computer boot process (swap from bios to on)
function digicompute.c:complete_boot(pos, index, name, param2)
minetest.swap_node({x = pos.x, y = pos.y, z = pos.z}, {name = name.."_on", param2 = param2})
-- Remove computer booting tag
computers[index].booting = nil
-- Update infotext
digicompute.c:infotext(pos)
-- 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())
-- Log boot in debug buffer
digicompute.c:print_debug(pos, "Booted")
end
-- [function] turn computer on
function digicompute.c:on(pos)
local temp = minetest.get_node(pos)
local ddef = minetest.registered_nodes[temp.name].digicompute
if ddef.state == "off" then
local name, param2 = temp.name, temp.param2
-- Swap to Bios
minetest.swap_node({x = pos.x, y = pos.y, z = pos.z}, {name = name.."_bios", param2 = param2}) -- set node to bios
-- Update infotext
digicompute.c:infotext(pos)
-- Save event so that if the game is exited mid-boot, the boot
-- process can be resumed immediately thereafter
local id = minetest.get_meta(pos):get_string("id")
computers[id].booting = true
-- Swap to on node after 2 seconds
minetest.after(2, function(pos_, index)
digicompute.c:complete_boot(pos_, index, name, param2)
end, vector.new(pos), id)
end
end
-- [function] turn computer off
function digicompute.c:off(pos, player)
local temp = minetest.get_node(pos) -- Get basic node information
local offname = "digicompute_redo:"..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
digicompute.c:infotext(pos)
-- Close formspec if player object is provided
if player and player.get_player_name then
minetest.close_formspec(player:get_player_name(), "")
end
-- Log action in debug buffer
digicompute.c:print_debug(pos, "Shut down")
-- Clear output buffer
meta:set_string("output", "")
-- Clear RAM
meta:set_string("ram", minetest.serialize({}))
-- Reset environment
digicompute.c:remove_env(pos)
end
-- [function] reboot computer
function digicompute.c:reboot(pos, player)
digicompute.c:off(pos, player)
digicompute.c:on(pos)
end
----------------------
-- NODE DEFINITIONS --
----------------------
function digicompute.register_computer(itemstring, def)
-- off
minetest.register_node("digicompute_redo:"..itemstring, {
digicompute = {
state = "off",
base = itemstring,
},
drawtype = "nodebox",
description = def.description,
tiles = def.off_tiles,
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky = 2},
drop = "digicompute_redo:"..itemstring,
sounds = default.node_sound_stone_defaults(),
node_box = def.node_box,
after_place_node = function(pos, player)
local meta = minetest.get_meta(pos)
meta:set_string("owner", player:get_player_name())
meta:set_string("input", "") -- Initialize input buffer
meta:set_string("output", "") -- Initialize output buffer
meta:set_string("debug", minetest.serialize({})) -- Initialize debug buffer
meta:set_string("system", minetest.serialize({})) -- Initialize system table
meta:set_string("ram", minetest.serialize({})) -- Initialize RAM preservation table
meta:set_string("help", "Type a command and press enter.") -- Initialize help
meta:set_string("output_editable", "false") -- Initialize uneditable output
meta:set_int("wrap_limit", 90) -- Initialize wrap chracter limit
digicompute.c:new_id(pos) -- Set up ID
-- Update infotext
digicompute.c:infotext(pos)
end,
on_rightclick = function(pos, node, player)
digicompute.c:on(pos)
end,
on_destruct = function(pos)
if minetest.get_meta(pos):get_string("name") then
digicompute.c:deinit(pos)
end
end,
})
-- bios
minetest.register_node("digicompute_redo:"..itemstring.."_bios", {
light_source = def.light_source or 7,
digicompute = {
state = "bios",
base = itemstring,
},
drawtype = "nodebox",
defription = def.defription,
tiles = def.bios_tiles,
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky = 2, not_in_creative_inventory = 1},
drop = "digicompute_redo:"..itemstring,
sounds = default.node_sound_stone_defaults(),
node_box = def.node_box,
on_destruct = function(pos)
if minetest.get_meta(pos):get_string("name") then
digicompute.c:deinit(pos)
end
end,
})
-- on
minetest.register_node("digicompute_redo:"..itemstring.."_on", {
light_source = def.light_source or 7,
digicompute = {
state = "on",
base = itemstring,
},
drawtype = "nodebox",
description = def.defription,
tiles = def.on_tiles,
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky = 2, not_in_creative_inventory = 1},
drop = "digicompute_redo:"..itemstring,
sounds = default.node_sound_stone_defaults(),
node_box = def.node_box,
on_rightclick = function(pos, node, player)
digicompute.c:open(pos, player)
end,
on_destruct = function(pos)
if minetest.get_meta(pos):get_string("name") then
digicompute.c:deinit(pos)
end
end,
})
end