summaryrefslogtreecommitdiff
path: root/builtin/common/after.lua
blob: bce2625370cd63f80ffdca83497895e937c9ec90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
local jobs = {}
local time = 0.0
local time_next = math.huge

core.register_globalstep(function(dtime)
	time = time + dtime

	if time < time_next then
		return
	end

	time_next = math.huge

	-- Iterate backwards so that we miss any new timers added by
	-- a timer callback.
	for i = #jobs, 1, -1 do
		local job = jobs[i]
		if time >= job.expire then
			core.set_last_run_mod(job.mod_origin)
			job.func(unpack(job.arg))
			local jobs_l = #jobs
			jobs[i] = jobs[jobs_l]
			jobs[jobs_l] = nil
		elseif job.expire < time_next then
			time_next = job.expire
		end
	end
end)

function core.after(after, func, ...)
	assert(tonumber(after) and type(func) == "function",
		"Invalid minetest.after invocation")
	local expire = time + after
	local new_job = {
		func = func,
		expire = expire,
		arg = {...},
		mod_origin = core.get_last_run_mod(),
	}

	jobs[#jobs + 1] = new_job
	time_next = math.min(time_next, expire)

	return {
		cancel = function()
			new_job.func = function() end
			new_job.args = {}
		end
	}
end