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