102 lines
2.8 KiB
Plaintext
102 lines
2.8 KiB
Plaintext
local table_remove = table.remove
|
|
local unpack = unpack
|
|
|
|
local function table_keys(t, is_array)
|
|
local a = {}
|
|
if is_array then
|
|
for i = 1, #t do
|
|
a[i] = i
|
|
end
|
|
else
|
|
for k,v in pairs(t) do
|
|
a[#a+1] = k
|
|
end
|
|
end
|
|
return a
|
|
end
|
|
|
|
-- Queue to span processing on each game tick
|
|
-- Arguments:
|
|
-- queue_name - name of queue
|
|
-- queue_table - table to process
|
|
-- func - function for processing, must have at least first 3 arguments: key of queue_table, value by that key, the number of key in processing order
|
|
-- returning true will remove element from queue, returning false or nil will leave it in queue for next process cycle
|
|
-- on_end_func - function at the end of queue processing, you can use this for chaining queue processing one after another
|
|
-- step - amount of items in queue to process at a time
|
|
-- ... - additional arguments for "func"
|
|
-- active_queues table contains names of queues that are active.
|
|
|
|
-- Example usage, get an object by id one at a time per game update
|
|
--[[
|
|
|
|
local ids = {1, 2, 3, 4, 5, 6, 7, 8}
|
|
process_queue("my_queue", ids, function(k, id, i)
|
|
local obj = level.object_by_id(id)
|
|
if obj then
|
|
printf("object %s, section %s, time_global %s", id, obj:section(), time_global())
|
|
end
|
|
return true
|
|
end, function()
|
|
printf("queue processed, final time %s", time_global())
|
|
end
|
|
)
|
|
|
|
]]
|
|
|
|
active_queues = {}
|
|
function process_queue(queue_name, queue_table, func, on_end_func, step, ...)
|
|
-- queue_table must be a table
|
|
if not queue_table or type(queue_table) ~= "table" then
|
|
printf("%s is not table, abort", queue_table)
|
|
return
|
|
end
|
|
|
|
if active_queues[queue_name] then
|
|
printf("queue %s is already active, abort", queue_name)
|
|
return
|
|
end
|
|
|
|
-- Collect table keys and initialize the table index
|
|
local i = 1
|
|
local keys = table_keys(queue_table)
|
|
local step = clamp(step or 1, 1, #keys)
|
|
|
|
local args = {...}
|
|
local update_func
|
|
update_func = function()
|
|
for s = 1, step do
|
|
local j = keys[i]
|
|
if func(j, queue_table[j], i, unpack(args)) == true then
|
|
queue_table[j] = nil
|
|
table_remove(keys, i)
|
|
i = i - 1
|
|
step = clamp(step, 1, #keys)
|
|
end
|
|
if not keys[1] then
|
|
if on_end_func then on_end_func() end
|
|
UnregisterScriptCallback("actor_on_update", update_func)
|
|
active_queues[queue_name] = nil
|
|
return
|
|
end
|
|
i = i == #keys and 1 or i + 1
|
|
end
|
|
end
|
|
active_queues[queue_name] = {
|
|
queue_table = queue_table,
|
|
func = update_func,
|
|
on_end_func = on_end_func,
|
|
step = step,
|
|
}
|
|
RegisterScriptCallback("actor_on_update", update_func)
|
|
end
|
|
|
|
function remove_queue(queue_name, on_end)
|
|
if active_queues[queue_name] then
|
|
if on_end and active_queues[queue_name].on_end_func then
|
|
active_queues[queue_name].on_end_func()
|
|
end
|
|
UnregisterScriptCallback("actor_on_update", active_queues[queue_name].func)
|
|
active_queues[queue_name] = nil
|
|
end
|
|
end
|