Fix computers frozen on bios after MT restart

Prevent computers from freezing on the BIOS node
after Minetest is restarted by adding a `booting`
flag to all computers waiting for the two seconds
to be over before the BIOS node is replaced with
the on node and by adding a coroutine which loops
through all the computers and replaces them with
"on" versions if they are stuck in BIOS.
master
octacian 2018-05-31 18:53:08 -07:00
parent 7bc3a5c6b1
commit e930f0715f
No known key found for this signature in database
GPG Key ID: E84291D11A3509B5
2 changed files with 61 additions and 9 deletions

View File

@ -171,6 +171,11 @@ 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:complete_boot(pos, index, name, param2)`
__Usage:__ `digicompute.c:complete_boot(<computer position (table)>, <computer ID (number)>, <base computer itemstring (string)>, <param2 value of computer (number)>)`
Completes the boot process of a computer by swapping the BIOS version of the computer node to the "on" version. This function should rarely be used, and currently is called only by `digicompute.c:on` inside a `minetest.after` which delays the boot completion by two seconds, and by the coroutine ensuring that all mid-boot computers complete the boot process even after Minetest restarts.
#### `c:on(pos)`
**Usage:** `digicompute.c:on(<computer position (table)>)`

View File

@ -73,6 +73,40 @@ end
-- [event] save computers on shutdown
minetest.register_on_shutdown(digicompute.save_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:"..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)
-------------------
---- FORMSPECS ----
-------------------
@ -348,6 +382,20 @@ function digicompute.c:reinit(pos)
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())
end
-- [function] turn computer on
function digicompute.c:on(pos)
local temp = minetest.get_node(pos)
@ -361,16 +409,15 @@ function digicompute.c:on(pos)
-- Update infotext
digicompute.c:infotext(pos)
-- Swap to on node after 2 seconds
minetest.after(2, function(pos_)
minetest.swap_node({x = pos_.x, y = pos_.y, z = pos_.z}, {name = name.."_on", param2 = param2})
-- 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
-- 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())
end, vector.new(pos))
-- 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