mirror of
https://github.com/minetest-mods/mesecons.git
synced 2025-07-02 07:40:20 +02:00
First draft of some kind of Action Queue (just like the globalstep queue in to_update), but more flexible and also including delay functionality (mesecon_delayer).
The queue is also saved to a file, so that when restarting mesecons, delayers resume to the state they had when the game shut down. Needs testing.
This commit is contained in:
90
mesecons/actionqueue.lua
Normal file
90
mesecons/actionqueue.lua
Normal file
@ -0,0 +1,90 @@
|
||||
mesecon.queue.actions={} -- contains all ActionQueue actions
|
||||
|
||||
function mesecon.queue:add_function(name, func)
|
||||
mesecon.queue.funcs[name] = func
|
||||
end
|
||||
|
||||
-- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
|
||||
-- use overwritecheck nil to never overwrite, but just add the event to the queue
|
||||
function mesecon.queue:add_action(pos, func, params, time, overwritecheck)
|
||||
-- Create Action Table:
|
||||
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
|
||||
action = { pos=pos,
|
||||
func=func,
|
||||
params=mesecon:tablecopy(params),
|
||||
time=time,
|
||||
owcheck=overwritecheck}
|
||||
|
||||
--print(dump(action))
|
||||
-- if not using the queue, (MESECONS_GLOBALSTEP off), just execute the function an we're done
|
||||
if not MESECONS_GLOBALSTEP then
|
||||
mesecon.queue:execute(action)
|
||||
return
|
||||
end
|
||||
|
||||
-- Otherwise, add the action to the queue
|
||||
if overwritecheck then -- check if old action has to be overwritten / removed:
|
||||
for i, ac in ipairs(mesecon.queue.actions) do
|
||||
if(mesecon:cmpPos(pos, action.pos)
|
||||
and mesecon:cmpAny(overwritecheck, ac.owcheck)) then
|
||||
table.remove(mesecon.queue.actions, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(mesecon.queue.actions, action)
|
||||
end
|
||||
|
||||
-- execute the stored functions on a globalstep
|
||||
-- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
|
||||
-- this makes sure that resuming mesecons circuits when restarting minetest works fine
|
||||
-- However, even that does not work in some cases, that's why we delay the time the globalsteps
|
||||
-- start to be execute by 5 seconds
|
||||
local m_time = 0
|
||||
minetest.register_globalstep(function (dtime)
|
||||
m_time = m_time + dtime
|
||||
if (m_time < 5) then return end -- don't even try if server has not been running for 2 seconds
|
||||
local actions = mesecon:tablecopy(mesecon.queue.actions)
|
||||
mesecon.queue.actions = {}
|
||||
|
||||
for i, action in ipairs(actions) do
|
||||
if action.time > 0 then
|
||||
action.time = action.time - dtime
|
||||
table.insert(mesecon.queue.actions, action) -- will be handled another time
|
||||
else -- execute and remove
|
||||
mesecon.queue:execute(action)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function mesecon.queue:execute(action)
|
||||
mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
|
||||
end
|
||||
|
||||
|
||||
-- Store and read the ActionQueue to / from a file
|
||||
-- so that upcoming actions are remembered when the game
|
||||
-- is restarted
|
||||
|
||||
local wpath = minetest.get_worldpath()
|
||||
local function file2table(filename)
|
||||
local f = io.open(filename, "r")
|
||||
if f==nil then return {} end
|
||||
local t = f:read("*all")
|
||||
f:close()
|
||||
if t=="" or t==nil then return {} end
|
||||
return minetest.deserialize(t)
|
||||
end
|
||||
|
||||
local function table2file(filename, table)
|
||||
local f = io.open(filename, "w")
|
||||
f:write(minetest.serialize(table))
|
||||
f:close()
|
||||
end
|
||||
|
||||
mesecon.queue.actions = file2table(wpath.."/mesecon_actionqueue")
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
mesecon.queue.actions = table2file(wpath.."/mesecon_actionqueue", mesecon.queue.actions)
|
||||
end)
|
Reference in New Issue
Block a user