diff options
Diffstat (limited to 'actionqueue.lua')
-rw-r--r-- | actionqueue.lua | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/actionqueue.lua b/actionqueue.lua new file mode 100644 index 0000000..3f1862f --- /dev/null +++ b/actionqueue.lua @@ -0,0 +1,74 @@ +-- smarter mesecons actionqueue +-- TODO: create PR if ot works properly + + +-- 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 get_highest_priority = function (actions) + local highestp = -1 + local highesti + for i, ac in ipairs(actions) do + if ac.priority > highestp then + highestp = ac.priority + highesti = i + end + end + + return highesti +end + +local m_time = 0 +local resumetime = mesecon.setting("resumetime", 4) +minetest.register_globalstep(function (dtime) + m_time = m_time + dtime + -- 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 + if (m_time < resumetime) then return end + + if not mesecons_debug.enabled then + return + end + + local actions = mesecon.tablecopy(mesecon.queue.actions) + local actions_now={} + + mesecon.queue.actions = {} + + -- sort actions into two categories: + -- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions) + for _, 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) + end + end + + if #actions_now > 30000 then + -- too much actions, purge them + return + end + + local t0 = minetest.get_us_time() + + while(#actions_now > 0) do -- execute highest priorities first, until all are executed + local hp = get_highest_priority(actions_now) + local action = actions_now[hp] + + local t1 = minetest.get_us_time() + local diff = t1 - t0 + if diff > 75000 then + -- execute remaining actions in next globalstep + table.insert(mesecon.queue.actions, 1, action) + else + mesecon.queue:execute(action) + table.remove(actions_now, hp) + end + + end +end) + |