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
							 |