actionqueue.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. mesecon.queue.actions={} -- contains all ActionQueue actions
  2. function mesecon.queue:add_function(name, func)
  3. mesecon.queue.funcs[name] = func
  4. end
  5. -- If add_action with twice the same overwritecheck and same position are called, the first one is overwritten
  6. -- use overwritecheck nil to never overwrite, but just add the event to the queue
  7. -- priority specifies the order actions are executed within one globalstep, highest first
  8. -- should be between 0 and 1
  9. function mesecon.queue:add_action(pos, func, params, time, overwritecheck, priority)
  10. -- Create Action Table:
  11. time = time or 0 -- time <= 0 --> execute, time > 0 --> wait time until execution
  12. priority = priority or 1
  13. local action = { pos=mesecon.tablecopy(pos),
  14. func=func,
  15. params=mesecon.tablecopy(params or {}),
  16. time=time,
  17. owcheck=(overwritecheck and mesecon.tablecopy(overwritecheck)) or nil,
  18. priority=priority}
  19. local toremove = nil
  20. -- Otherwise, add the action to the queue
  21. if overwritecheck then -- check if old action has to be overwritten / removed:
  22. for i, ac in ipairs(mesecon.queue.actions) do
  23. if(vector.equals(pos, ac.pos)
  24. and mesecon.cmpAny(overwritecheck, ac.owcheck)) then
  25. toremove = i
  26. break
  27. end
  28. end
  29. end
  30. if (toremove ~= nil) then
  31. table.remove(mesecon.queue.actions, toremove)
  32. end
  33. table.insert(mesecon.queue.actions, action)
  34. end
  35. -- execute the stored functions on a globalstep
  36. -- if however, the pos of a function is not loaded (get_node_or_nil == nil), do NOT execute the function
  37. -- this makes sure that resuming mesecons circuits when restarting minetest works fine
  38. -- However, even that does not work in some cases, that's why we delay the time the globalsteps
  39. -- start to be execute by 5 seconds
  40. local get_highest_priority = function (actions)
  41. local highestp = -1
  42. local highesti
  43. for i, ac in ipairs(actions) do
  44. if ac.priority > highestp then
  45. highestp = ac.priority
  46. highesti = i
  47. end
  48. end
  49. return highesti
  50. end
  51. local m_time = 0
  52. local resumetime = mesecon.setting("resumetime", 4)
  53. minetest.register_globalstep(function (dtime)
  54. m_time = m_time + dtime
  55. -- don't even try if server has not been running for XY seconds; resumetime = time to wait
  56. -- after starting the server before processing the ActionQueue, don't set this too low
  57. if (m_time < resumetime) then return end
  58. local actions = mesecon.tablecopy(mesecon.queue.actions)
  59. local actions_now={}
  60. mesecon.queue.actions = {}
  61. -- sort actions into two categories:
  62. -- those toexecute now (actions_now) and those to execute later (mesecon.queue.actions)
  63. for i, ac in ipairs(actions) do
  64. if ac.time > 0 then
  65. ac.time = ac.time - dtime -- executed later
  66. table.insert(mesecon.queue.actions, ac)
  67. else
  68. table.insert(actions_now, ac)
  69. end
  70. end
  71. while(#actions_now > 0) do -- execute highest priorities first, until all are executed
  72. local hp = get_highest_priority(actions_now)
  73. mesecon.queue:execute(actions_now[hp])
  74. table.remove(actions_now, hp)
  75. end
  76. end)
  77. function mesecon.queue:execute(action)
  78. -- ignore if action queue function name doesn't exist,
  79. -- (e.g. in case the action queue savegame was written by an old mesecons version)
  80. if mesecon.queue.funcs[action.func] then
  81. mesecon.queue.funcs[action.func](action.pos, unpack(action.params))
  82. end
  83. end
  84. -- Store and read the ActionQueue to / from a file
  85. -- so that upcoming actions are remembered when the game
  86. -- is restarted
  87. mesecon.queue.actions = mesecon.file2table("mesecon_actionqueue")
  88. minetest.register_on_shutdown(function()
  89. mesecon.table2file("mesecon_actionqueue", mesecon.queue.actions)
  90. end)