-
Notifications
You must be signed in to change notification settings - Fork 6
/
task.lua
156 lines (135 loc) · 3.37 KB
/
task.lua
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
local resume,status=coroutine.resume,coroutine.status
local assert,rawset=assert,rawset
local rem=table.remove
local timer=ZENITHA.timer.getTime
local TASK={}
-- Locks
---@type Map<number>
local locks=setmetatable({},{
__index=function(self,k) rawset(self,k,-1e99) return -1e99 end,
__newindex=function(self,k) rawset(self,k,-1e99) end,
})
---Attempt to set a labeled lock
---
---Can only succeed if the same-name lock is not set or has expired
---
---### Example
---```lua
----- Making 'name' sound cannot be played in next 0.26 seconds
---if TASK.lock('sound_name',0.26) then playSound('name') end
---```
---@param name any
---@param time? number
---@return boolean
function TASK.lock(name,time)
if timer()>=locks[name] then
locks[name]=timer()+(time or 1e99)
return true
else
return false
end
end
---Same as `TASK.lock`, but lock will be forced set even if the lock is not expired
---@param name any
---@param time? number
---@return boolean
function TASK.forceLock(name,time)
local res=timer()>=locks[name]
locks[name]=timer()+(time or 1e99)
return res
end
---Invalidate a lock
---@param name any
function TASK.unlock(name)
locks[name]=-1e99
end
---Get the time remaining of a lock, false if not locked or expired
---@param name any
---@return number | false
function TASK.getLock(name)
local v=locks[name]-timer()
return v>0 and v
end
---Remove the locks which are already expired
function TASK.freshLock()
for k,v in next,locks do
if timer()>v then locks[k]=nil end
end
end
---Invalidate all locks
function TASK.clearLock()
for k in next,locks do
locks[k]=nil
end
end
local tasks={}
---Update all tasks (called by Zenitha)
---@param dt number
function TASK._update(dt)
for i=#tasks,1,-1 do
local T=tasks[i]
if status(T.thread)=='dead' then
rem(tasks,i)
else
assert(resume(T.thread,dt))
end
end
end
---Create a new task
---@param code function
---@param ... any Arguments passed to the function
function TASK.new(code,...)
local thread=coroutine.create(code)
assert(resume(thread,...))
if status(thread)~='dead' then
tasks[#tasks+1]={
thread=thread,
code=code,
args={...},
}
end
end
---Get the number of tasks
---@return number
function TASK.getCount()
return #tasks
end
---Remove task(s) by specified code(the function which created the task)
---@param code function
function TASK.removeTask_code(code)
for i=#tasks,1,-1 do
if tasks[i].code==code then
rem(tasks,i)
end
end
end
---Iterate through tasks, remove them if the given function returns true
---@param func function
---@param ... any Arguments passed to the given function
function TASK.removeTask_iterate(func,...)
for i=#tasks,1,-1 do
if func(tasks[i],...) then
rem(tasks,i)
end
end
end
---Remove all tasks
function TASK.clear()
TABLE.clear(tasks)
end
local yield=coroutine.yield
---Yield for some times
---@param count number
function TASK.yieldN(count)
for _=1,count do yield() end
end
---Yield for some seconds
function TASK.yieldT(time)
local t=timer()
while timer()-t<time do yield() end
end
---Yield until the scene swapping animation finished
function TASK.yieldUntilNextScene()
while SCN.swapping do yield() end
end
return TASK