summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/game/misc.lua90
-rw-r--r--doc/lua_api.txt2
2 files changed, 33 insertions, 59 deletions
diff --git a/builtin/game/misc.lua b/builtin/game/misc.lua
index efd0f8dc7..bacadf18f 100644
--- a/builtin/game/misc.lua
+++ b/builtin/game/misc.lua
@@ -4,74 +4,48 @@
-- Misc. API functions
--
-local timers = {}
-local mintime
-local function update_timers(delay)
- mintime = false
- local sub = 0
- for index = 1, #timers do
- index = index - sub
- local timer = timers[index]
- timer.time = timer.time - delay
- if timer.time <= 0 then
- core.set_last_run_mod(timer.mod_origin)
- timer.func(unpack(timer.args or {}))
- table.remove(timers, index)
- sub = sub + 1
- elseif mintime then
- mintime = math.min(mintime, timer.time)
- else
- mintime = timer.time
- end
- end
-end
+local jobs = {}
+local time = 0.0
+local last = 0.0
-local timers_to_add
-local function add_timers()
- for _, timer in ipairs(timers_to_add) do
- table.insert(timers, timer)
+core.register_globalstep(function(dtime)
+ local new = core.get_us_time() / 1000000
+ if new > last then
+ time = time + (new - last)
+ else
+ -- Overflow, we may lose a little bit of time here but
+ -- only 1 tick max, potentially running timers slightly
+ -- too early.
+ time = time + new
end
- timers_to_add = false
-end
+ last = new
-local delay = 0
-core.register_globalstep(function(dtime)
- if not mintime then
- -- abort if no timers are running
+ if #jobs < 1 then
return
end
- if timers_to_add then
- add_timers()
- end
- delay = delay + dtime
- if delay < mintime then
- return
+
+ -- Iterate backwards so that we miss any new timers added by
+ -- a timer callback, and so that we don't skip the next timer
+ -- in the list if we remove one.
+ 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))
+ table.remove(jobs, i)
+ end
end
- update_timers(delay)
- delay = 0
end)
-function core.after(time, func, ...)
+function core.after(after, func, ...)
assert(tonumber(time) and type(func) == "function",
"Invalid core.after invocation")
- if not mintime then
- mintime = time
- timers_to_add = {{
- time = time+delay,
- func = func,
- args = {...},
- mod_origin = core.get_last_run_mod(),
- }}
- return
- end
- mintime = math.min(mintime, time)
- timers_to_add = timers_to_add or {}
- timers_to_add[#timers_to_add+1] = {
- time = time+delay,
- func = func,
- args = {...},
- mod_origin = core.get_last_run_mod(),
- }
+ table.insert(jobs, {
+ func = func,
+ expire = time + after,
+ arg = {...},
+ mod_origin = core.get_last_run_mod()
+ })
end
function core.check_player_privs(player_or_name, ...)
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 7255852e0..b6bc957c1 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -2242,7 +2242,7 @@ These functions return the leftover itemstack.
### Timing
* `minetest.after(time, func, ...)`
- * Call the function `func` after `time` seconds
+ * Call the function `func` after `time` seconds, may be fractional
* Optional: Variable number of arguments that are passed to `func`
### Server