61 lines
1.8 KiB
Lua
61 lines
1.8 KiB
Lua
---@class ActionQueue
|
|
---@field queue table<any, { coroutine: thread, expireTimeMs: number }>
|
|
actionQueue = {
|
|
queue = {},
|
|
}
|
|
|
|
---@alias Action fun(deltaSeconds: number)
|
|
|
|
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
|
|
|
|
function actionQueue:newOnly(id, maxTimeMs, action)
|
|
if self.queue[id] then
|
|
return
|
|
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
|
|
|
|
-- luacheck: ignore
|
|
if not playdate or playdate.TEST_MODE then
|
|
return actionQueue
|
|
end
|