2014-01-10 22:29:18 +01:00
|
|
|
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
|
2014-03-19 10:20:43 +01:00
|
|
|
-- priority specifies the order actions are executed within one globalstep, highest first
|
2014-01-11 10:04:32 +01:00
|
|
|
-- should be between 0 and 1
|
|
|
|
function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
|
2014-01-10 22:29:18 +01:00
|
|
|
-- Create Action Table:
|
|
|
|
time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
|
2014-01-11 10:04:32 +01:00
|
|
|
priority = priority or 1
|
2014-03-19 10:20:43 +01:00
|
|
|
local action = { pos=mesecon:tablecopy(pos),
|
|
|
|
func=func,
|
|
|
|
params=mesecon:tablecopy(params),
|
|
|
|
time=time,
|
|
|
|
owcheck=(overwritecheck and mesecon:tablecopy(overwritecheck)) or nil,
|
|
|
|
priority=priority}
|
2014-01-10 22:29:18 +01:00
|
|
|
|
|
|
|
-- if not using the queue, (MESECONS_GLOBALSTEP off), just execute the function an we're done
|
2014-01-19 13:57:11 +01:00
|
|
|
if not MESECONS_GLOBALSTEP and action.time == 0 then
|
2014-01-10 22:29:18 +01:00
|
|
|
mesecon.queue:execute(action)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2014-01-11 16:46:27 +01:00
|
|
|
local toremove = nil
|
2014-01-10 22:29:18 +01:00
|
|
|
-- 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
|
2014-01-11 08:57:21 +01:00
|
|
|
if(mesecon:cmpPos(pos, ac.pos)
|
2014-01-10 22:29:18 +01:00
|
|
|
and mesecon:cmpAny(overwritecheck, ac.owcheck)) then
|
2014-01-11 16:46:27 +01:00
|
|
|
toremove = i
|
2014-01-10 22:29:18 +01:00
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-01-11 16:46:27 +01:00
|
|
|
if (toremove ~= nil) then
|
2014-01-11 20:03:37 +01:00
|
|
|
table.remove(mesecon.queue.actions, toremove)
|
2014-01-11 16:46:27 +01:00
|
|
|
end
|
|
|
|
|
2014-01-10 22:29:18 +01:00
|
|
|
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
|
2014-01-11 10:04:32 +01:00
|
|
|
local get_highest_priority = function (actions)
|
2014-03-19 10:20:43 +01:00
|
|
|
local highestp = -1, highesti
|
2014-01-11 10:04:32 +01:00
|
|
|
for i, ac in ipairs(actions) do
|
|
|
|
if ac.priority > highestp then
|
|
|
|
highestp = ac.priority
|
|
|
|
highesti = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return highesti
|
|
|
|
end
|
|
|
|
|
2014-01-10 22:29:18 +01:00
|
|
|
local m_time = 0
|
|
|
|
minetest.register_globalstep(function (dtime)
|
|
|
|
m_time = m_time + dtime
|
2014-01-19 13:57:11 +01:00
|
|
|
if (m_time < MESECONS_RESUMETIME) then return end -- don't even try if server has not been running for XY seconds
|
2014-01-10 22:29:18 +01:00
|
|
|
local actions = mesecon:tablecopy(mesecon.queue.actions)
|
2014-01-11 15:36:30 +01:00
|
|
|
local actions_now={}
|
|
|
|
|
2014-01-10 22:29:18 +01:00
|
|
|
mesecon.queue.actions = {}
|
|
|
|
|
2014-03-19 10:20:43 +01:00
|
|
|
-- sort actions into two categories:
|
|
|
|
-- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions)
|
2014-01-11 15:36:30 +01:00
|
|
|
for i, ac in ipairs(actions) do
|
|
|
|
if ac.time > 0 then
|
|
|
|
ac.time = ac.time - dtime -- executed later
|
|
|
|
table.insert(mesecon.queue.actions, ac)
|
|
|
|
else
|
|
|
|
table.insert(actions_now, ac)
|
2014-01-10 22:29:18 +01:00
|
|
|
end
|
|
|
|
end
|
2014-01-11 10:04:32 +01:00
|
|
|
|
2014-01-11 15:36:30 +01:00
|
|
|
while(#actions_now > 0) do -- execute highest priorities first, until all are executed
|
|
|
|
local hp = get_highest_priority(actions_now)
|
|
|
|
mesecon.queue:execute(actions_now[hp])
|
|
|
|
table.remove(actions_now, hp)
|
2014-01-11 10:04:32 +01:00
|
|
|
end
|
2014-01-10 22:29:18 +01:00
|
|
|
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)
|