roblox-opencode 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -122
- package/commands/setup-game.md +108 -108
- package/commands/sync-check.md +53 -53
- package/core/roblox-core.md +93 -93
- package/dist/server.js +189 -167
- package/package.json +35 -35
- package/skills/roblox-analytics/SKILL.md +277 -277
- package/skills/roblox-analytics/references/event-batcher.luau +75 -75
- package/skills/roblox-animation-vfx/SKILL.md +1325 -1325
- package/skills/roblox-architecture/SKILL.md +877 -863
- package/skills/roblox-architecture/references/combat-systems.md +1381 -1381
- package/skills/roblox-code-review/SKILL.md +686 -686
- package/skills/roblox-data/SKILL.md +889 -889
- package/skills/roblox-data/references/inventory-systems.md +1729 -1729
- package/skills/roblox-debug/SKILL.md +98 -98
- package/skills/roblox-gui/SKILL.md +1103 -1103
- package/skills/roblox-gui-fusion/SKILL.md +150 -150
- package/skills/roblox-gui-fusion/references/inventory.luau +427 -427
- package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -579
- package/skills/roblox-gui-fusion/references/shop.luau +411 -411
- package/skills/roblox-luau-mastery/SKILL.md +1618 -1519
- package/skills/roblox-monetization/SKILL.md +1084 -1084
- package/skills/roblox-monetization/references/process-receipt.luau +131 -131
- package/skills/roblox-networking/SKILL.md +669 -669
- package/skills/roblox-networking/references/remote-validator.luau +193 -193
- package/skills/roblox-publish-checklist/SKILL.md +127 -127
- package/skills/roblox-runtime/SKILL.md +753 -753
- package/skills/roblox-sharp-edges/SKILL.md +294 -294
- package/skills/roblox-sync/SKILL.md +126 -126
- package/skills/roblox-testing/SKILL.md +943 -943
- package/skills/roblox-tooling/SKILL.md +149 -149
- package/vendor/LICENSES/ProfileStore-LICENSE +201 -201
- package/vendor/LICENSES/RbxUtil-LICENSE +7 -7
- package/vendor/LICENSES/promise-LICENSE +20 -20
- package/vendor/LICENSES/t-LICENSE +21 -21
- package/vendor/LICENSES/testez-LICENSE +200 -200
- package/vendor/README.md +83 -83
- package/vendor/fusion/Animation/ExternalTime.luau +83 -83
- package/vendor/fusion/Animation/Spring.luau +321 -321
- package/vendor/fusion/Animation/Stopwatch.luau +127 -127
- package/vendor/fusion/Animation/Tween.luau +187 -187
- package/vendor/fusion/Animation/getTweenDuration.luau +27 -27
- package/vendor/fusion/Animation/getTweenRatio.luau +47 -47
- package/vendor/fusion/Animation/lerpType.luau +163 -163
- package/vendor/fusion/Animation/packType.luau +99 -99
- package/vendor/fusion/Animation/springCoefficients.luau +80 -80
- package/vendor/fusion/Animation/unpackType.luau +102 -102
- package/vendor/fusion/Colour/Oklab.luau +70 -70
- package/vendor/fusion/Colour/sRGB.luau +54 -54
- package/vendor/fusion/External.luau +167 -167
- package/vendor/fusion/ExternalDebug.luau +69 -69
- package/vendor/fusion/Graph/Observer.luau +113 -113
- package/vendor/fusion/Graph/castToGraph.luau +28 -28
- package/vendor/fusion/Graph/change.luau +80 -80
- package/vendor/fusion/Graph/depend.luau +32 -32
- package/vendor/fusion/Graph/evaluate.luau +55 -55
- package/vendor/fusion/Instances/Attribute.luau +57 -57
- package/vendor/fusion/Instances/AttributeChange.luau +46 -46
- package/vendor/fusion/Instances/AttributeOut.luau +63 -63
- package/vendor/fusion/Instances/Child.luau +21 -21
- package/vendor/fusion/Instances/Children.luau +147 -147
- package/vendor/fusion/Instances/Hydrate.luau +32 -32
- package/vendor/fusion/Instances/New.luau +52 -52
- package/vendor/fusion/Instances/OnChange.luau +49 -49
- package/vendor/fusion/Instances/OnEvent.luau +53 -53
- package/vendor/fusion/Instances/Out.luau +69 -69
- package/vendor/fusion/Instances/applyInstanceProps.luau +148 -148
- package/vendor/fusion/Instances/defaultProps.luau +194 -194
- package/vendor/fusion/LICENSE +21 -21
- package/vendor/fusion/Logging/formatError.luau +48 -48
- package/vendor/fusion/Logging/messages.luau +51 -51
- package/vendor/fusion/Logging/parseError.luau +24 -24
- package/vendor/fusion/Memory/checkLifetime.luau +133 -133
- package/vendor/fusion/Memory/deriveScope.luau +23 -23
- package/vendor/fusion/Memory/deriveScopeImpl.luau +44 -44
- package/vendor/fusion/Memory/doCleanup.luau +78 -78
- package/vendor/fusion/Memory/innerScope.luau +33 -33
- package/vendor/fusion/Memory/legacyCleanup.luau +17 -17
- package/vendor/fusion/Memory/needsDestruction.luau +16 -16
- package/vendor/fusion/Memory/poisonScope.luau +33 -33
- package/vendor/fusion/Memory/scopePool.luau +54 -54
- package/vendor/fusion/Memory/scoped.luau +26 -26
- package/vendor/fusion/Memory/whichLivesLonger.luau +74 -74
- package/vendor/fusion/RobloxExternal.luau +97 -97
- package/vendor/fusion/State/Computed.luau +138 -138
- package/vendor/fusion/State/For/Disassembly.luau +210 -210
- package/vendor/fusion/State/For/ForTypes.luau +30 -30
- package/vendor/fusion/State/For/init.luau +109 -109
- package/vendor/fusion/State/ForKeys.luau +93 -93
- package/vendor/fusion/State/ForPairs.luau +96 -96
- package/vendor/fusion/State/ForValues.luau +93 -93
- package/vendor/fusion/State/Value.luau +87 -87
- package/vendor/fusion/State/castToState.luau +25 -25
- package/vendor/fusion/State/peek.luau +30 -30
- package/vendor/fusion/Types.luau +314 -314
- package/vendor/fusion/Utility/Contextual.luau +90 -90
- package/vendor/fusion/Utility/Safe.luau +22 -22
- package/vendor/fusion/Utility/isSimilar.luau +29 -29
- package/vendor/fusion/Utility/merge.luau +35 -35
- package/vendor/fusion/Utility/nameOf.luau +34 -34
- package/vendor/fusion/Utility/never.luau +13 -13
- package/vendor/fusion/Utility/nicknames.luau +10 -10
- package/vendor/fusion/Utility/xtypeof.luau +26 -26
- package/vendor/fusion/init.luau +82 -82
- package/vendor/profilestore/init.luau +2242 -2242
- package/vendor/promise/init.luau +1982 -1982
- package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -25
- package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -228
- package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -269
- package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -223
- package/vendor/rbxutil/buffer-util/Types.luau +60 -60
- package/vendor/rbxutil/buffer-util/index.d.ts +153 -153
- package/vendor/rbxutil/buffer-util/init.luau +41 -41
- package/vendor/rbxutil/buffer-util/package.json +16 -16
- package/vendor/rbxutil/buffer-util/wally.toml +9 -9
- package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -232
- package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -156
- package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -109
- package/vendor/rbxutil/comm/Client/init.luau +135 -135
- package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -295
- package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -211
- package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -211
- package/vendor/rbxutil/comm/Server/init.luau +140 -140
- package/vendor/rbxutil/comm/Types.luau +18 -18
- package/vendor/rbxutil/comm/Util.luau +27 -27
- package/vendor/rbxutil/comm/init.luau +35 -35
- package/vendor/rbxutil/comm/wally.toml +13 -13
- package/vendor/rbxutil/component/init.luau +759 -759
- package/vendor/rbxutil/component/init.test.luau +311 -311
- package/vendor/rbxutil/component/wally.toml +14 -14
- package/vendor/rbxutil/concur/init.luau +542 -542
- package/vendor/rbxutil/concur/init.test.luau +364 -364
- package/vendor/rbxutil/concur/wally.toml +8 -8
- package/vendor/rbxutil/enum-list/init.luau +101 -101
- package/vendor/rbxutil/enum-list/init.test.luau +91 -91
- package/vendor/rbxutil/enum-list/wally.toml +8 -8
- package/vendor/rbxutil/find/index.d.ts +20 -20
- package/vendor/rbxutil/find/init.luau +44 -44
- package/vendor/rbxutil/find/package.json +17 -17
- package/vendor/rbxutil/find/wally.toml +8 -8
- package/vendor/rbxutil/input/Gamepad.luau +559 -559
- package/vendor/rbxutil/input/Keyboard.luau +124 -124
- package/vendor/rbxutil/input/Mouse.luau +278 -278
- package/vendor/rbxutil/input/PreferredInput.luau +91 -91
- package/vendor/rbxutil/input/Touch.luau +120 -120
- package/vendor/rbxutil/input/init.luau +33 -33
- package/vendor/rbxutil/input/wally.toml +12 -12
- package/vendor/rbxutil/loader/index.d.ts +15 -15
- package/vendor/rbxutil/loader/init.luau +137 -137
- package/vendor/rbxutil/loader/wally.toml +8 -8
- package/vendor/rbxutil/log/index.d.ts +38 -38
- package/vendor/rbxutil/log/init.luau +746 -746
- package/vendor/rbxutil/log/wally.toml +8 -8
- package/vendor/rbxutil/net/init.luau +190 -190
- package/vendor/rbxutil/net/wally.toml +8 -8
- package/vendor/rbxutil/option/index.d.ts +44 -44
- package/vendor/rbxutil/option/init.luau +489 -489
- package/vendor/rbxutil/option/init.test.luau +342 -342
- package/vendor/rbxutil/option/wally.toml +8 -8
- package/vendor/rbxutil/pid/index.d.ts +53 -53
- package/vendor/rbxutil/pid/init.luau +195 -195
- package/vendor/rbxutil/pid/package.json +16 -16
- package/vendor/rbxutil/pid/wally.toml +9 -9
- package/vendor/rbxutil/quaternion/index.d.ts +117 -117
- package/vendor/rbxutil/quaternion/init.luau +570 -570
- package/vendor/rbxutil/quaternion/package.json +16 -16
- package/vendor/rbxutil/quaternion/wally.toml +9 -9
- package/vendor/rbxutil/query/index.d.ts +43 -43
- package/vendor/rbxutil/query/init.luau +117 -117
- package/vendor/rbxutil/query/package.json +18 -18
- package/vendor/rbxutil/query/wally.toml +9 -9
- package/vendor/rbxutil/sequent/index.d.ts +28 -28
- package/vendor/rbxutil/sequent/init.luau +340 -340
- package/vendor/rbxutil/sequent/package.json +16 -16
- package/vendor/rbxutil/sequent/wally.toml +9 -9
- package/vendor/rbxutil/ser/init.luau +175 -175
- package/vendor/rbxutil/ser/init.test.luau +50 -50
- package/vendor/rbxutil/ser/wally.toml +11 -11
- package/vendor/rbxutil/shake/index.d.ts +36 -36
- package/vendor/rbxutil/shake/init.luau +532 -532
- package/vendor/rbxutil/shake/init.test.luau +267 -267
- package/vendor/rbxutil/shake/package.json +16 -16
- package/vendor/rbxutil/shake/wally.toml +9 -9
- package/vendor/rbxutil/signal/index.d.ts +100 -100
- package/vendor/rbxutil/signal/init.luau +432 -432
- package/vendor/rbxutil/signal/init.test.luau +190 -190
- package/vendor/rbxutil/signal/package.json +17 -17
- package/vendor/rbxutil/signal/wally.toml +9 -9
- package/vendor/rbxutil/silo/TableWatcher.luau +65 -65
- package/vendor/rbxutil/silo/Util.luau +55 -55
- package/vendor/rbxutil/silo/init.luau +338 -338
- package/vendor/rbxutil/silo/init.test.luau +215 -215
- package/vendor/rbxutil/silo/wally.toml +8 -8
- package/vendor/rbxutil/spring/index.d.ts +40 -40
- package/vendor/rbxutil/spring/init.luau +97 -97
- package/vendor/rbxutil/spring/package.json +17 -17
- package/vendor/rbxutil/spring/wally.toml +8 -8
- package/vendor/rbxutil/stream/index.d.ts +88 -88
- package/vendor/rbxutil/stream/init.luau +597 -597
- package/vendor/rbxutil/stream/package.json +18 -18
- package/vendor/rbxutil/stream/wally.toml +9 -9
- package/vendor/rbxutil/streamable/Streamable.luau +202 -202
- package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -80
- package/vendor/rbxutil/streamable/init.luau +8 -8
- package/vendor/rbxutil/streamable/wally.toml +12 -12
- package/vendor/rbxutil/symbol/init.luau +56 -56
- package/vendor/rbxutil/symbol/init.test.luau +37 -37
- package/vendor/rbxutil/symbol/wally.toml +8 -8
- package/vendor/rbxutil/table-util/init.luau +938 -938
- package/vendor/rbxutil/table-util/init.test.luau +439 -439
- package/vendor/rbxutil/task-queue/index.d.ts +27 -27
- package/vendor/rbxutil/task-queue/init.luau +97 -97
- package/vendor/rbxutil/task-queue/wally.toml +8 -8
- package/vendor/rbxutil/timer/index.d.ts +81 -81
- package/vendor/rbxutil/timer/init.luau +249 -249
- package/vendor/rbxutil/timer/init.test.luau +73 -73
- package/vendor/rbxutil/timer/wally.toml +11 -11
- package/vendor/rbxutil/tree/index.d.ts +15 -15
- package/vendor/rbxutil/tree/init.luau +137 -137
- package/vendor/rbxutil/tree/wally.toml +8 -8
- package/vendor/rbxutil/trove/index.d.ts +46 -46
- package/vendor/rbxutil/trove/init.luau +787 -787
- package/vendor/rbxutil/trove/init.test.luau +203 -203
- package/vendor/rbxutil/trove/wally.toml +8 -8
- package/vendor/rbxutil/typed-remote/init.luau +196 -196
- package/vendor/rbxutil/typed-remote/wally.toml +8 -8
- package/vendor/rbxutil/wait-for/index.d.ts +17 -17
- package/vendor/rbxutil/wait-for/init.luau +257 -257
- package/vendor/rbxutil/wait-for/init.test.luau +182 -182
- package/vendor/rbxutil/wait-for/wally.toml +11 -11
- package/vendor/t/t.lua +1350 -1350
- package/vendor/testez/Context.lua +26 -26
- package/vendor/testez/Expectation.lua +311 -311
- package/vendor/testez/ExpectationContext.lua +38 -38
- package/vendor/testez/LifecycleHooks.lua +89 -89
- package/vendor/testez/Reporters/TeamCityReporter.lua +101 -101
- package/vendor/testez/Reporters/TextReporter.lua +105 -105
- package/vendor/testez/Reporters/TextReporterQuiet.lua +96 -96
- package/vendor/testez/TestBootstrap.lua +146 -146
- package/vendor/testez/TestEnum.lua +27 -27
- package/vendor/testez/TestPlan.lua +304 -304
- package/vendor/testez/TestPlanner.lua +39 -39
- package/vendor/testez/TestResults.lua +111 -111
- package/vendor/testez/TestRunner.lua +188 -188
- package/vendor/testez/TestSession.lua +243 -243
- package/vendor/testez/init.lua +39 -39
|
@@ -1,249 +1,249 @@
|
|
|
1
|
-
--!strict
|
|
2
|
-
|
|
3
|
-
local RunService = game:GetService("RunService")
|
|
4
|
-
|
|
5
|
-
local Signal = require(script.Parent.Signal)
|
|
6
|
-
|
|
7
|
-
--[=[
|
|
8
|
-
@within Timer
|
|
9
|
-
@type CallbackFn () -> ()
|
|
10
|
-
Callback function.
|
|
11
|
-
]=]
|
|
12
|
-
type CallbackFn = () -> nil
|
|
13
|
-
|
|
14
|
-
--[=[
|
|
15
|
-
@within Timer
|
|
16
|
-
@type TimeFn () -> number
|
|
17
|
-
Time function.
|
|
18
|
-
]=]
|
|
19
|
-
type TimeFn = () -> number
|
|
20
|
-
|
|
21
|
-
--[=[
|
|
22
|
-
@class Timer
|
|
23
|
-
|
|
24
|
-
The Timer class allows for code to run periodically at specified intervals.
|
|
25
|
-
|
|
26
|
-
```lua
|
|
27
|
-
local timer = Timer.new(2)
|
|
28
|
-
timer.Tick:Connect(function()
|
|
29
|
-
print("Tock")
|
|
30
|
-
end)
|
|
31
|
-
timer:Start()
|
|
32
|
-
```
|
|
33
|
-
]=]
|
|
34
|
-
local Timer = {}
|
|
35
|
-
Timer.__index = Timer
|
|
36
|
-
|
|
37
|
-
export type Timer = typeof(setmetatable(
|
|
38
|
-
{} :: {
|
|
39
|
-
Interval: number,
|
|
40
|
-
UpdateSignal: RBXScriptSignal,
|
|
41
|
-
TimeFunction: () -> number,
|
|
42
|
-
AllowDrift: boolean,
|
|
43
|
-
Tick: Signal.Signal<>,
|
|
44
|
-
|
|
45
|
-
_runHandle: RBXScriptConnection?,
|
|
46
|
-
},
|
|
47
|
-
Timer
|
|
48
|
-
))
|
|
49
|
-
|
|
50
|
-
--[=[
|
|
51
|
-
@within Timer
|
|
52
|
-
@prop Interval number
|
|
53
|
-
Interval at which the `Tick` event fires.
|
|
54
|
-
]=]
|
|
55
|
-
--[=[
|
|
56
|
-
@within Timer
|
|
57
|
-
@prop UpdateSignal RBXScriptSignal | Signal
|
|
58
|
-
The signal which updates the timer internally.
|
|
59
|
-
]=]
|
|
60
|
-
--[=[
|
|
61
|
-
@within Timer
|
|
62
|
-
@prop TimeFunction TimeFn
|
|
63
|
-
The function which gets the current time.
|
|
64
|
-
]=]
|
|
65
|
-
--[=[
|
|
66
|
-
@within Timer
|
|
67
|
-
@prop AllowDrift boolean
|
|
68
|
-
Flag which indicates if the timer is allowed to drift. This
|
|
69
|
-
is set to `true` by default. This flag must be set before
|
|
70
|
-
calling `Start` or `StartNow`. This flag should only be set
|
|
71
|
-
to `false` if it is necessary for drift to be eliminated.
|
|
72
|
-
]=]
|
|
73
|
-
--[=[
|
|
74
|
-
@within Timer
|
|
75
|
-
@prop Tick RBXScriptSignal | Signal
|
|
76
|
-
The event which is fired every time the timer hits its interval.
|
|
77
|
-
]=]
|
|
78
|
-
|
|
79
|
-
--[=[
|
|
80
|
-
@return Timer
|
|
81
|
-
|
|
82
|
-
Creates a new timer.
|
|
83
|
-
]=]
|
|
84
|
-
function Timer.new(interval: number): Timer
|
|
85
|
-
assert(type(interval) == "number", "argument #1 to Timer.new must be a number; got " .. type(interval))
|
|
86
|
-
assert(interval >= 0, "argument #1 to Timer.new must be greater or equal to 0; got " .. tostring(interval))
|
|
87
|
-
|
|
88
|
-
local self = setmetatable({}, Timer)
|
|
89
|
-
|
|
90
|
-
self._runHandle = nil
|
|
91
|
-
self.Interval = interval
|
|
92
|
-
self.UpdateSignal = RunService.Heartbeat
|
|
93
|
-
self.TimeFunction = time
|
|
94
|
-
self.AllowDrift = true
|
|
95
|
-
self.Tick = Signal.new()
|
|
96
|
-
|
|
97
|
-
return self
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
--[=[
|
|
101
|
-
@return RBXScriptConnection
|
|
102
|
-
|
|
103
|
-
Creates a simplified timer which just fires off a callback function at the given interval.
|
|
104
|
-
|
|
105
|
-
```lua
|
|
106
|
-
-- Basic:
|
|
107
|
-
Timer.simple(1, function()
|
|
108
|
-
print("Tick")
|
|
109
|
-
end)
|
|
110
|
-
|
|
111
|
-
-- Using other arguments:
|
|
112
|
-
Timer.simple(1, function()
|
|
113
|
-
print("Tick")
|
|
114
|
-
end, true, RunService.Heartbeat, os.clock)
|
|
115
|
-
```
|
|
116
|
-
]=]
|
|
117
|
-
function Timer.simple(
|
|
118
|
-
interval: number,
|
|
119
|
-
callback: CallbackFn,
|
|
120
|
-
startNow: boolean?,
|
|
121
|
-
updateSignal: RBXScriptSignal?,
|
|
122
|
-
timeFn: TimeFn?
|
|
123
|
-
)
|
|
124
|
-
local update = updateSignal or RunService.Heartbeat
|
|
125
|
-
local t = timeFn or time
|
|
126
|
-
local nextTick = t() + interval
|
|
127
|
-
|
|
128
|
-
if startNow then
|
|
129
|
-
task.defer(callback)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
return update:Connect(function()
|
|
133
|
-
local now = t()
|
|
134
|
-
if now >= nextTick then
|
|
135
|
-
nextTick = now + interval
|
|
136
|
-
task.defer(callback)
|
|
137
|
-
end
|
|
138
|
-
end)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
--[=[
|
|
142
|
-
Returns `true` if the given object is a Timer.
|
|
143
|
-
]=]
|
|
144
|
-
function Timer.is(obj: any): boolean
|
|
145
|
-
return type(obj) == "table" and getmetatable(obj) == Timer
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
function Timer._startTimer(self: Timer)
|
|
149
|
-
local t = self.TimeFunction
|
|
150
|
-
local nextTick = t() + self.Interval
|
|
151
|
-
|
|
152
|
-
self._runHandle = self.UpdateSignal:Connect(function()
|
|
153
|
-
local now = t()
|
|
154
|
-
if now >= nextTick then
|
|
155
|
-
nextTick = now + self.Interval
|
|
156
|
-
self.Tick:Fire()
|
|
157
|
-
end
|
|
158
|
-
end)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
function Timer._startTimerNoDrift(self: Timer)
|
|
162
|
-
assert(self.Interval > 0, "interval must be greater than 0 when AllowDrift is set to false")
|
|
163
|
-
|
|
164
|
-
local t = self.TimeFunction
|
|
165
|
-
local n = 1
|
|
166
|
-
local start = t()
|
|
167
|
-
local nextTick = start + self.Interval
|
|
168
|
-
self._runHandle = self.UpdateSignal:Connect(function()
|
|
169
|
-
local now = t()
|
|
170
|
-
while now >= nextTick do
|
|
171
|
-
n += 1
|
|
172
|
-
nextTick = start + (self.Interval * n)
|
|
173
|
-
self.Tick:Fire()
|
|
174
|
-
end
|
|
175
|
-
end)
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
--[=[
|
|
179
|
-
Starts the timer. Will do nothing if the timer is already running.
|
|
180
|
-
|
|
181
|
-
```lua
|
|
182
|
-
timer:Start()
|
|
183
|
-
```
|
|
184
|
-
]=]
|
|
185
|
-
function Timer.Start(self: Timer)
|
|
186
|
-
if self._runHandle then
|
|
187
|
-
return
|
|
188
|
-
end
|
|
189
|
-
if self.AllowDrift then
|
|
190
|
-
self:_startTimer()
|
|
191
|
-
else
|
|
192
|
-
self:_startTimerNoDrift()
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
--[=[
|
|
197
|
-
Starts the timer and fires off the Tick event immediately. Will do
|
|
198
|
-
nothing if the timer is already running.
|
|
199
|
-
|
|
200
|
-
```lua
|
|
201
|
-
timer:StartNow()
|
|
202
|
-
```
|
|
203
|
-
]=]
|
|
204
|
-
function Timer.StartNow(self: Timer)
|
|
205
|
-
if self._runHandle then
|
|
206
|
-
return
|
|
207
|
-
end
|
|
208
|
-
self.Tick:Fire()
|
|
209
|
-
self:Start()
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
--[=[
|
|
213
|
-
Stops the timer. Will do nothing if the timer is already stopped.
|
|
214
|
-
|
|
215
|
-
```lua
|
|
216
|
-
timer:Stop()
|
|
217
|
-
```
|
|
218
|
-
]=]
|
|
219
|
-
function Timer.Stop(self: Timer)
|
|
220
|
-
if not self._runHandle then
|
|
221
|
-
return
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
self._runHandle:Disconnect()
|
|
225
|
-
self._runHandle = nil
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
--[=[
|
|
229
|
-
Returns `true` if the timer is currently running.
|
|
230
|
-
|
|
231
|
-
```lua
|
|
232
|
-
if timer:IsRunning() then
|
|
233
|
-
-- Do something
|
|
234
|
-
end
|
|
235
|
-
```
|
|
236
|
-
]=]
|
|
237
|
-
function Timer.IsRunning(self: Timer): boolean
|
|
238
|
-
return self._runHandle ~= nil
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
--[=[
|
|
242
|
-
Destroys the timer. This will also stop the timer.
|
|
243
|
-
]=]
|
|
244
|
-
function Timer.Destroy(self: Timer)
|
|
245
|
-
self.Tick:Destroy()
|
|
246
|
-
self:Stop()
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
return Timer
|
|
1
|
+
--!strict
|
|
2
|
+
|
|
3
|
+
local RunService = game:GetService("RunService")
|
|
4
|
+
|
|
5
|
+
local Signal = require(script.Parent.Signal)
|
|
6
|
+
|
|
7
|
+
--[=[
|
|
8
|
+
@within Timer
|
|
9
|
+
@type CallbackFn () -> ()
|
|
10
|
+
Callback function.
|
|
11
|
+
]=]
|
|
12
|
+
type CallbackFn = () -> nil
|
|
13
|
+
|
|
14
|
+
--[=[
|
|
15
|
+
@within Timer
|
|
16
|
+
@type TimeFn () -> number
|
|
17
|
+
Time function.
|
|
18
|
+
]=]
|
|
19
|
+
type TimeFn = () -> number
|
|
20
|
+
|
|
21
|
+
--[=[
|
|
22
|
+
@class Timer
|
|
23
|
+
|
|
24
|
+
The Timer class allows for code to run periodically at specified intervals.
|
|
25
|
+
|
|
26
|
+
```lua
|
|
27
|
+
local timer = Timer.new(2)
|
|
28
|
+
timer.Tick:Connect(function()
|
|
29
|
+
print("Tock")
|
|
30
|
+
end)
|
|
31
|
+
timer:Start()
|
|
32
|
+
```
|
|
33
|
+
]=]
|
|
34
|
+
local Timer = {}
|
|
35
|
+
Timer.__index = Timer
|
|
36
|
+
|
|
37
|
+
export type Timer = typeof(setmetatable(
|
|
38
|
+
{} :: {
|
|
39
|
+
Interval: number,
|
|
40
|
+
UpdateSignal: RBXScriptSignal,
|
|
41
|
+
TimeFunction: () -> number,
|
|
42
|
+
AllowDrift: boolean,
|
|
43
|
+
Tick: Signal.Signal<>,
|
|
44
|
+
|
|
45
|
+
_runHandle: RBXScriptConnection?,
|
|
46
|
+
},
|
|
47
|
+
Timer
|
|
48
|
+
))
|
|
49
|
+
|
|
50
|
+
--[=[
|
|
51
|
+
@within Timer
|
|
52
|
+
@prop Interval number
|
|
53
|
+
Interval at which the `Tick` event fires.
|
|
54
|
+
]=]
|
|
55
|
+
--[=[
|
|
56
|
+
@within Timer
|
|
57
|
+
@prop UpdateSignal RBXScriptSignal | Signal
|
|
58
|
+
The signal which updates the timer internally.
|
|
59
|
+
]=]
|
|
60
|
+
--[=[
|
|
61
|
+
@within Timer
|
|
62
|
+
@prop TimeFunction TimeFn
|
|
63
|
+
The function which gets the current time.
|
|
64
|
+
]=]
|
|
65
|
+
--[=[
|
|
66
|
+
@within Timer
|
|
67
|
+
@prop AllowDrift boolean
|
|
68
|
+
Flag which indicates if the timer is allowed to drift. This
|
|
69
|
+
is set to `true` by default. This flag must be set before
|
|
70
|
+
calling `Start` or `StartNow`. This flag should only be set
|
|
71
|
+
to `false` if it is necessary for drift to be eliminated.
|
|
72
|
+
]=]
|
|
73
|
+
--[=[
|
|
74
|
+
@within Timer
|
|
75
|
+
@prop Tick RBXScriptSignal | Signal
|
|
76
|
+
The event which is fired every time the timer hits its interval.
|
|
77
|
+
]=]
|
|
78
|
+
|
|
79
|
+
--[=[
|
|
80
|
+
@return Timer
|
|
81
|
+
|
|
82
|
+
Creates a new timer.
|
|
83
|
+
]=]
|
|
84
|
+
function Timer.new(interval: number): Timer
|
|
85
|
+
assert(type(interval) == "number", "argument #1 to Timer.new must be a number; got " .. type(interval))
|
|
86
|
+
assert(interval >= 0, "argument #1 to Timer.new must be greater or equal to 0; got " .. tostring(interval))
|
|
87
|
+
|
|
88
|
+
local self = setmetatable({}, Timer)
|
|
89
|
+
|
|
90
|
+
self._runHandle = nil
|
|
91
|
+
self.Interval = interval
|
|
92
|
+
self.UpdateSignal = RunService.Heartbeat
|
|
93
|
+
self.TimeFunction = time
|
|
94
|
+
self.AllowDrift = true
|
|
95
|
+
self.Tick = Signal.new()
|
|
96
|
+
|
|
97
|
+
return self
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
--[=[
|
|
101
|
+
@return RBXScriptConnection
|
|
102
|
+
|
|
103
|
+
Creates a simplified timer which just fires off a callback function at the given interval.
|
|
104
|
+
|
|
105
|
+
```lua
|
|
106
|
+
-- Basic:
|
|
107
|
+
Timer.simple(1, function()
|
|
108
|
+
print("Tick")
|
|
109
|
+
end)
|
|
110
|
+
|
|
111
|
+
-- Using other arguments:
|
|
112
|
+
Timer.simple(1, function()
|
|
113
|
+
print("Tick")
|
|
114
|
+
end, true, RunService.Heartbeat, os.clock)
|
|
115
|
+
```
|
|
116
|
+
]=]
|
|
117
|
+
function Timer.simple(
|
|
118
|
+
interval: number,
|
|
119
|
+
callback: CallbackFn,
|
|
120
|
+
startNow: boolean?,
|
|
121
|
+
updateSignal: RBXScriptSignal?,
|
|
122
|
+
timeFn: TimeFn?
|
|
123
|
+
)
|
|
124
|
+
local update = updateSignal or RunService.Heartbeat
|
|
125
|
+
local t = timeFn or time
|
|
126
|
+
local nextTick = t() + interval
|
|
127
|
+
|
|
128
|
+
if startNow then
|
|
129
|
+
task.defer(callback)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
return update:Connect(function()
|
|
133
|
+
local now = t()
|
|
134
|
+
if now >= nextTick then
|
|
135
|
+
nextTick = now + interval
|
|
136
|
+
task.defer(callback)
|
|
137
|
+
end
|
|
138
|
+
end)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
--[=[
|
|
142
|
+
Returns `true` if the given object is a Timer.
|
|
143
|
+
]=]
|
|
144
|
+
function Timer.is(obj: any): boolean
|
|
145
|
+
return type(obj) == "table" and getmetatable(obj) == Timer
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
function Timer._startTimer(self: Timer)
|
|
149
|
+
local t = self.TimeFunction
|
|
150
|
+
local nextTick = t() + self.Interval
|
|
151
|
+
|
|
152
|
+
self._runHandle = self.UpdateSignal:Connect(function()
|
|
153
|
+
local now = t()
|
|
154
|
+
if now >= nextTick then
|
|
155
|
+
nextTick = now + self.Interval
|
|
156
|
+
self.Tick:Fire()
|
|
157
|
+
end
|
|
158
|
+
end)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
function Timer._startTimerNoDrift(self: Timer)
|
|
162
|
+
assert(self.Interval > 0, "interval must be greater than 0 when AllowDrift is set to false")
|
|
163
|
+
|
|
164
|
+
local t = self.TimeFunction
|
|
165
|
+
local n = 1
|
|
166
|
+
local start = t()
|
|
167
|
+
local nextTick = start + self.Interval
|
|
168
|
+
self._runHandle = self.UpdateSignal:Connect(function()
|
|
169
|
+
local now = t()
|
|
170
|
+
while now >= nextTick do
|
|
171
|
+
n += 1
|
|
172
|
+
nextTick = start + (self.Interval * n)
|
|
173
|
+
self.Tick:Fire()
|
|
174
|
+
end
|
|
175
|
+
end)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
--[=[
|
|
179
|
+
Starts the timer. Will do nothing if the timer is already running.
|
|
180
|
+
|
|
181
|
+
```lua
|
|
182
|
+
timer:Start()
|
|
183
|
+
```
|
|
184
|
+
]=]
|
|
185
|
+
function Timer.Start(self: Timer)
|
|
186
|
+
if self._runHandle then
|
|
187
|
+
return
|
|
188
|
+
end
|
|
189
|
+
if self.AllowDrift then
|
|
190
|
+
self:_startTimer()
|
|
191
|
+
else
|
|
192
|
+
self:_startTimerNoDrift()
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
--[=[
|
|
197
|
+
Starts the timer and fires off the Tick event immediately. Will do
|
|
198
|
+
nothing if the timer is already running.
|
|
199
|
+
|
|
200
|
+
```lua
|
|
201
|
+
timer:StartNow()
|
|
202
|
+
```
|
|
203
|
+
]=]
|
|
204
|
+
function Timer.StartNow(self: Timer)
|
|
205
|
+
if self._runHandle then
|
|
206
|
+
return
|
|
207
|
+
end
|
|
208
|
+
self.Tick:Fire()
|
|
209
|
+
self:Start()
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
--[=[
|
|
213
|
+
Stops the timer. Will do nothing if the timer is already stopped.
|
|
214
|
+
|
|
215
|
+
```lua
|
|
216
|
+
timer:Stop()
|
|
217
|
+
```
|
|
218
|
+
]=]
|
|
219
|
+
function Timer.Stop(self: Timer)
|
|
220
|
+
if not self._runHandle then
|
|
221
|
+
return
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
self._runHandle:Disconnect()
|
|
225
|
+
self._runHandle = nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
--[=[
|
|
229
|
+
Returns `true` if the timer is currently running.
|
|
230
|
+
|
|
231
|
+
```lua
|
|
232
|
+
if timer:IsRunning() then
|
|
233
|
+
-- Do something
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
]=]
|
|
237
|
+
function Timer.IsRunning(self: Timer): boolean
|
|
238
|
+
return self._runHandle ~= nil
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
--[=[
|
|
242
|
+
Destroys the timer. This will also stop the timer.
|
|
243
|
+
]=]
|
|
244
|
+
function Timer.Destroy(self: Timer)
|
|
245
|
+
self.Tick:Destroy()
|
|
246
|
+
self:Stop()
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
return Timer
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
local ServerScriptService = game:GetService("ServerScriptService")
|
|
2
|
-
|
|
3
|
-
local Test = require(ServerScriptService.TestRunner.Test)
|
|
4
|
-
|
|
5
|
-
return function(ctx: Test.TestContext)
|
|
6
|
-
local Timer = require(script.Parent)
|
|
7
|
-
|
|
8
|
-
ctx:Describe("Timer", function()
|
|
9
|
-
local timer
|
|
10
|
-
|
|
11
|
-
ctx:BeforeEach(function()
|
|
12
|
-
timer = Timer.new(0.1)
|
|
13
|
-
timer.TimeFunction = os.clock
|
|
14
|
-
end)
|
|
15
|
-
|
|
16
|
-
ctx:AfterEach(function()
|
|
17
|
-
if timer then
|
|
18
|
-
timer:Destroy()
|
|
19
|
-
timer = nil
|
|
20
|
-
end
|
|
21
|
-
end)
|
|
22
|
-
|
|
23
|
-
ctx:Test("should create a new timer", function()
|
|
24
|
-
ctx:Expect(Timer.is(timer)):ToBe(true)
|
|
25
|
-
end)
|
|
26
|
-
|
|
27
|
-
ctx:Test("should tick appropriately", function()
|
|
28
|
-
local start = os.clock()
|
|
29
|
-
timer:Start()
|
|
30
|
-
timer.Tick:Wait()
|
|
31
|
-
local duration = (os.clock() - start)
|
|
32
|
-
ctx:Expect(duration):ToBeNear(duration, 0.02)
|
|
33
|
-
end)
|
|
34
|
-
|
|
35
|
-
ctx:Test("should start immediately", function()
|
|
36
|
-
local start = os.clock()
|
|
37
|
-
local stop = nil
|
|
38
|
-
timer.Tick:Connect(function()
|
|
39
|
-
if not stop then
|
|
40
|
-
stop = os.clock()
|
|
41
|
-
end
|
|
42
|
-
end)
|
|
43
|
-
timer:StartNow()
|
|
44
|
-
timer.Tick:Wait()
|
|
45
|
-
ctx:Expect(stop):ToBeA("number")
|
|
46
|
-
local duration = (stop - start)
|
|
47
|
-
ctx:Expect(duration):ToBeNear(0, 0.02)
|
|
48
|
-
end)
|
|
49
|
-
|
|
50
|
-
ctx:Test("should stop", function()
|
|
51
|
-
local ticks = 0
|
|
52
|
-
timer.Tick:Connect(function()
|
|
53
|
-
ticks += 1
|
|
54
|
-
end)
|
|
55
|
-
timer:StartNow()
|
|
56
|
-
timer:Stop()
|
|
57
|
-
task.wait(1)
|
|
58
|
-
ctx:Expect(ticks):ToBe(1)
|
|
59
|
-
end)
|
|
60
|
-
|
|
61
|
-
ctx:Test("should detect if running", function()
|
|
62
|
-
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
63
|
-
timer:Start()
|
|
64
|
-
ctx:Expect(timer:IsRunning()):ToBe(true)
|
|
65
|
-
timer:Stop()
|
|
66
|
-
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
67
|
-
timer:StartNow()
|
|
68
|
-
ctx:Expect(timer:IsRunning()):ToBe(true)
|
|
69
|
-
timer:Stop()
|
|
70
|
-
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
71
|
-
end)
|
|
72
|
-
end)
|
|
73
|
-
end
|
|
1
|
+
local ServerScriptService = game:GetService("ServerScriptService")
|
|
2
|
+
|
|
3
|
+
local Test = require(ServerScriptService.TestRunner.Test)
|
|
4
|
+
|
|
5
|
+
return function(ctx: Test.TestContext)
|
|
6
|
+
local Timer = require(script.Parent)
|
|
7
|
+
|
|
8
|
+
ctx:Describe("Timer", function()
|
|
9
|
+
local timer
|
|
10
|
+
|
|
11
|
+
ctx:BeforeEach(function()
|
|
12
|
+
timer = Timer.new(0.1)
|
|
13
|
+
timer.TimeFunction = os.clock
|
|
14
|
+
end)
|
|
15
|
+
|
|
16
|
+
ctx:AfterEach(function()
|
|
17
|
+
if timer then
|
|
18
|
+
timer:Destroy()
|
|
19
|
+
timer = nil
|
|
20
|
+
end
|
|
21
|
+
end)
|
|
22
|
+
|
|
23
|
+
ctx:Test("should create a new timer", function()
|
|
24
|
+
ctx:Expect(Timer.is(timer)):ToBe(true)
|
|
25
|
+
end)
|
|
26
|
+
|
|
27
|
+
ctx:Test("should tick appropriately", function()
|
|
28
|
+
local start = os.clock()
|
|
29
|
+
timer:Start()
|
|
30
|
+
timer.Tick:Wait()
|
|
31
|
+
local duration = (os.clock() - start)
|
|
32
|
+
ctx:Expect(duration):ToBeNear(duration, 0.02)
|
|
33
|
+
end)
|
|
34
|
+
|
|
35
|
+
ctx:Test("should start immediately", function()
|
|
36
|
+
local start = os.clock()
|
|
37
|
+
local stop = nil
|
|
38
|
+
timer.Tick:Connect(function()
|
|
39
|
+
if not stop then
|
|
40
|
+
stop = os.clock()
|
|
41
|
+
end
|
|
42
|
+
end)
|
|
43
|
+
timer:StartNow()
|
|
44
|
+
timer.Tick:Wait()
|
|
45
|
+
ctx:Expect(stop):ToBeA("number")
|
|
46
|
+
local duration = (stop - start)
|
|
47
|
+
ctx:Expect(duration):ToBeNear(0, 0.02)
|
|
48
|
+
end)
|
|
49
|
+
|
|
50
|
+
ctx:Test("should stop", function()
|
|
51
|
+
local ticks = 0
|
|
52
|
+
timer.Tick:Connect(function()
|
|
53
|
+
ticks += 1
|
|
54
|
+
end)
|
|
55
|
+
timer:StartNow()
|
|
56
|
+
timer:Stop()
|
|
57
|
+
task.wait(1)
|
|
58
|
+
ctx:Expect(ticks):ToBe(1)
|
|
59
|
+
end)
|
|
60
|
+
|
|
61
|
+
ctx:Test("should detect if running", function()
|
|
62
|
+
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
63
|
+
timer:Start()
|
|
64
|
+
ctx:Expect(timer:IsRunning()):ToBe(true)
|
|
65
|
+
timer:Stop()
|
|
66
|
+
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
67
|
+
timer:StartNow()
|
|
68
|
+
ctx:Expect(timer:IsRunning()):ToBe(true)
|
|
69
|
+
timer:Stop()
|
|
70
|
+
ctx:Expect(timer:IsRunning()):ToBe(false)
|
|
71
|
+
end)
|
|
72
|
+
end)
|
|
73
|
+
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "sleitnick/timer"
|
|
3
|
-
description = "Timer class"
|
|
4
|
-
version = "2.0.0"
|
|
5
|
-
license = "MIT"
|
|
6
|
-
authors = ["Stephen Leitnick"]
|
|
7
|
-
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
-
realm = "shared"
|
|
9
|
-
|
|
10
|
-
[dependencies]
|
|
11
|
-
Signal = "sleitnick/signal@^2"
|
|
1
|
+
[package]
|
|
2
|
+
name = "sleitnick/timer"
|
|
3
|
+
description = "Timer class"
|
|
4
|
+
version = "2.0.0"
|
|
5
|
+
license = "MIT"
|
|
6
|
+
authors = ["Stephen Leitnick"]
|
|
7
|
+
registry = "https://github.com/UpliftGames/wally-index"
|
|
8
|
+
realm = "shared"
|
|
9
|
+
|
|
10
|
+
[dependencies]
|
|
11
|
+
Signal = "sleitnick/signal@^2"
|