BatterUp/src/action-queue.lua

47 lines
1.6 KiB
Lua

-- selene: allow(unscoped_variables)
actionQueue = {
---@type table<any, { coroutine: thread, expireTimeMs: number }>
queue = {},
}
---@alias Action fun(deltaSeconds: number)
--selene: allow(incorrect_standard_library_use)
local close = coroutine.close
--- Added actions will be called on every runWaiting() update.
--- They will continue to be executed until they return Succeeded or Failed instead of NeedsMoreTime.
---
--- Replaces any existing action with the given id.
--- If the initial call of action() doesn't return NeedsMoreTime, this function will not bother adding it to the queue.
---@param id any
---@param maxTimeMs number
---@param action Action
function actionQueue:upsert(id, maxTimeMs, action)
if self.queue[id] then
close(self.queue[id].coroutine)
end
self.queue[id] = {
coroutine = coroutine.create(action),
expireTimeMs = maxTimeMs + playdate.getCurrentTimeMilliseconds(),
}
end
--- Must be called on every playdate.update() to check for (and run) any waiting tasks.
--- Actions that return NeedsMoreTime will not be removed from the queue unless they have expired.
function actionQueue:runWaiting(deltaSeconds)
local currentTimeMs = playdate.getCurrentTimeMilliseconds()
for id, actionObject in pairs(self.queue) do
coroutine.resume(actionObject.coroutine, deltaSeconds)
if currentTimeMs > actionObject.expireTimeMs then
close(actionObject.coroutine)
end
if coroutine.status(actionObject.coroutine) == "dead" then
self.queue[id] = nil
end
end
end