some documentation and hopefully no breaking anymore

This commit is contained in:
DS-Minetest 2019-12-29 15:39:47 +01:00
parent b00fab6c48
commit dce6943149
1 changed files with 48 additions and 26 deletions

View File

@ -1,3 +1,28 @@
--[[
Mesecons uses something it calls an ActionQueue.
The ActionQueue holds functions and actions.
Functions are added on load time with a specified name.
Actions are preserved over server restarts.
Each action consists of a position, the name of an added function to be called,
the params that should be used in this function call (additionally to the pos),
the time after which it should be executed, an optional overwritecheck and a
priority.
If time = 0, the action will be executed in the next globalstep, otherwise the
earliest globalstep when it will be executed is the after next globalstep.
It is guaranteed, that for two actions ac1, ac2 where ac1 ~= ac2,
ac1.time == ac2.time, ac1.priority == ac2.priority and ac1 was added earlier
than ac2, ac1 will be executed before ac2 (but in the same globalstep).
Note: Do not pass references in params, as they can not be preserved.
Also note: Some of the guarantees here might be dropped at some time.
]]
-- localize for speed -- localize for speed
local queue = mesecon.queue local queue = mesecon.queue
@ -29,49 +54,46 @@ function queue:add_action(pos, func, params, time, overwritecheck, priority)
for i, ac in ipairs(queue.actions) do for i, ac in ipairs(queue.actions) do
if vector.equals(pos, ac.pos) if vector.equals(pos, ac.pos)
and mesecon.cmpAny(overwritecheck, ac.owcheck) then and mesecon.cmpAny(overwritecheck, ac.owcheck) then
-- replace the old action -- remove the old action
queue.actions[i] = action table.remove(queue.actions, i)
return break
end end
end end
end end
-- otherwise just add to queue
table.insert(queue.actions, action) table.insert(queue.actions, action)
end end
-- execute the stored functions on a globalstep -- 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 -- 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 -- this makes sure that resuming mesecons circuits when restarting minetest works fine (hm, where do we do this?)
-- However, even that does not work in some cases, that's why we delay the time the globalsteps -- However, even that does not work in some cases, that's why we delay the time the globalsteps
-- start to be execute by 5 (4?) seconds -- start to be execute by 4 seconds
local function globalstep_func(dtime) local function globalstep_func(dtime)
-- sort out the actions to execute now (actions_now) local actions = queue.actions
-- split into two categories:
-- actions_now: actions to execute now
-- queue.actions: actions to execute later
local actions_now = {} local actions_now = {}
local actions_count = #queue.actions queue.actions = {}
-- iterating downwards makes it easier to remove actions for _, ac in ipairs(actions) do
for i = actions_count, 1, -1 do if ac.time > 0 then
local ac = queue.actions[i] -- action ac is to be executed later
ac.time = ac.time - dtime -- ~> insert into queue.actions
ac.time = ac.time - dtime
if ac.time <= 0 then table.insert(queue.actions, ac)
else
-- action ac is to be executed now -- action ac is to be executed now
-- ~> insert into actions_now -- ~> insert into actions_now
table.insert(actions_now, ac) table.insert(actions_now, ac)
-- ~> remove from queue.actions
queue.actions[i] = queue.actions[actions_count]
queue.actions[actions_count] = nil
actions_count = actions_count - 1
end end
end end
-- stable-sort the executed actions after their priority -- stable-sort the executed actions after their priority
-- (some constructions might depend on the execution order for acions with delay 0) -- some constructions might depend on the execution order, hence we first
-- note that the actions were added in inverse order because of the downwards iteration, -- execute the actions that had a lower index in actions_now
-- hence we first execute the actions that had a higher index in actions_now
local old_action_order = {} local old_action_order = {}
for i, ac in ipairs(actions_now) do for i, ac in ipairs(actions_now) do
old_action_order[ac] = i old_action_order[ac] = i
@ -80,23 +102,23 @@ local function globalstep_func(dtime)
if ac1.priority ~= ac2.priority then if ac1.priority ~= ac2.priority then
return ac1.priority > ac2.priority return ac1.priority > ac2.priority
else else
return old_action_order[ac1] > old_action_order[ac2] return old_action_order[ac1] < old_action_order[ac2]
end end
end) end)
-- execute highest priorities first, until all are executed -- execute highest priorities first, until all are executed
for i, ac in ipairs(actions_now) do for _, ac in ipairs(actions_now) do
queue:execute(ac) queue:execute(ac)
end end
end end
-- delay the time the globalsteps start to be execute by 5 (4?) seconds -- delay the time the globalsteps start to be execute by 4 seconds
do do
local m_time = 0 local m_time = 0
local resumetime = mesecon.setting("resumetime", 4) local resumetime = mesecon.setting("resumetime", 4)
local globalstep_func_index = #minetest.registered_globalsteps + 1 local globalstep_func_index = #minetest.registered_globalsteps + 1
minetest.register_globalstep(function (dtime) minetest.register_globalstep(function(dtime)
m_time = m_time + dtime m_time = m_time + dtime
-- don't even try if server has not been running for XY seconds; resumetime = time to wait -- don't even try if server has not been running for XY seconds; resumetime = time to wait
-- after starting the server before processing the ActionQueue, don't set this too low -- after starting the server before processing the ActionQueue, don't set this too low