@quenty/cooldown 6.0.0-canary.367.e9fdcbc.0 → 6.0.0
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/CHANGELOG.md +132 -1
- package/package.json +19 -15
- package/src/Client/{CooldownClient.lua → Binders/CooldownClient.lua} +9 -4
- package/src/Client/CooldownServiceClient.lua +22 -0
- package/src/Server/Binders/Cooldown.lua +44 -0
- package/src/Server/CooldownService.lua +22 -0
- package/src/Shared/{CooldownBase.lua → Binders/CooldownBase.lua} +26 -42
- package/src/Shared/Binders/CooldownShared.lua +22 -0
- package/src/Shared/CooldownUtils.lua +4 -4
- package/src/Shared/Model/CooldownModel.lua +125 -0
- package/src/Shared/Model/CooldownTrackerModel.lua +70 -0
- package/src/Shared/Tracker/CooldownTracker.lua +81 -0
- package/src/Client/CooldownBindersClient.lua +0 -20
- package/src/Client/CooldownTracker.lua +0 -67
- package/src/Server/Cooldown.lua +0 -46
- package/src/Server/CooldownBindersServer.lua +0 -20
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,138 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
# [6.0.0
|
|
6
|
+
# [6.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.32.0...@quenty/cooldown@6.0.0) (2023-10-11)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add CooldownTrackerModel.isCooldownTrackerModel(value) ([8f0ade2](https://github.com/Quenty/NevermoreEngine/commit/8f0ade2ce96e70090ebab6085cf3f24696a7cca6))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [5.32.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.31.0...@quenty/cooldown@5.32.0) (2023-09-21)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# [5.31.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.30.0...@quenty/cooldown@5.31.0) (2023-09-04)
|
|
26
|
+
|
|
27
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# [5.30.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.29.0...@quenty/cooldown@5.30.0) (2023-08-23)
|
|
34
|
+
|
|
35
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# [5.29.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.28.0...@quenty/cooldown@5.29.0) (2023-08-01)
|
|
42
|
+
|
|
43
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# [5.28.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.27.0...@quenty/cooldown@5.28.0) (2023-07-28)
|
|
50
|
+
|
|
51
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# [5.27.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.26.1...@quenty/cooldown@5.27.0) (2023-07-23)
|
|
58
|
+
|
|
59
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## [5.26.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.26.0...@quenty/cooldown@5.26.1) (2023-07-18)
|
|
66
|
+
|
|
67
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# [5.26.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.25.1...@quenty/cooldown@5.26.0) (2023-07-15)
|
|
74
|
+
|
|
75
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## [5.25.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.25.0...@quenty/cooldown@5.25.1) (2023-07-11)
|
|
82
|
+
|
|
83
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# [5.25.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.24.2...@quenty/cooldown@5.25.0) (2023-07-10)
|
|
90
|
+
|
|
91
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
## [5.24.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.24.1...@quenty/cooldown@5.24.2) (2023-07-03)
|
|
98
|
+
|
|
99
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
## [5.24.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.24.0...@quenty/cooldown@5.24.1) (2023-06-24)
|
|
106
|
+
|
|
107
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# [5.24.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.23.1...@quenty/cooldown@5.24.0) (2023-06-24)
|
|
114
|
+
|
|
115
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## [5.23.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.23.0...@quenty/cooldown@5.23.1) (2023-06-23)
|
|
122
|
+
|
|
123
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# [5.23.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.22.0...@quenty/cooldown@5.23.0) (2023-06-17)
|
|
130
|
+
|
|
131
|
+
**Note:** Version bump only for package @quenty/cooldown
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# [5.22.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.21.0...@quenty/cooldown@5.22.0) (2023-06-05)
|
|
7
138
|
|
|
8
139
|
**Note:** Version bump only for package @quenty/cooldown
|
|
9
140
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/cooldown",
|
|
3
|
-
"version": "6.0.0
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Generalized networked cooldown system for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -25,22 +25,26 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@quenty/attributeutils": "
|
|
29
|
-
"@quenty/baseobject": "
|
|
30
|
-
"@quenty/binder": "9.0.0
|
|
31
|
-
"@quenty/
|
|
32
|
-
"@quenty/
|
|
33
|
-
"@quenty/
|
|
34
|
-
"@quenty/
|
|
35
|
-
"@quenty/
|
|
36
|
-
"@quenty/
|
|
37
|
-
"@quenty/
|
|
38
|
-
"@quenty/
|
|
39
|
-
"@quenty/
|
|
40
|
-
"@quenty/
|
|
28
|
+
"@quenty/attributeutils": "^9.0.0",
|
|
29
|
+
"@quenty/baseobject": "^7.0.0",
|
|
30
|
+
"@quenty/binder": "^9.0.0",
|
|
31
|
+
"@quenty/ducktype": "^2.0.0",
|
|
32
|
+
"@quenty/instanceutils": "^8.0.0",
|
|
33
|
+
"@quenty/loader": "^7.0.0",
|
|
34
|
+
"@quenty/maid": "^2.6.0",
|
|
35
|
+
"@quenty/promise": "^7.0.0",
|
|
36
|
+
"@quenty/propertyvalue": "^2.0.0",
|
|
37
|
+
"@quenty/remoting": "^7.0.0",
|
|
38
|
+
"@quenty/rx": "^8.0.0",
|
|
39
|
+
"@quenty/rxbinderutils": "^9.0.0",
|
|
40
|
+
"@quenty/servicebag": "^7.0.0",
|
|
41
|
+
"@quenty/signal": "^3.0.0",
|
|
42
|
+
"@quenty/table": "^3.3.0",
|
|
43
|
+
"@quenty/timesyncservice": "^8.0.0",
|
|
44
|
+
"@quenty/valueobject": "^8.0.0"
|
|
41
45
|
},
|
|
42
46
|
"publishConfig": {
|
|
43
47
|
"access": "public"
|
|
44
48
|
},
|
|
45
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "fdeae46099587019ec5fc15317dc673aed379400"
|
|
46
50
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
local require = require(script.Parent.loader).load(script)
|
|
9
9
|
|
|
10
10
|
local CooldownBase = require("CooldownBase")
|
|
11
|
+
local Binder = require("Binder")
|
|
11
12
|
|
|
12
13
|
local CooldownClient = setmetatable({}, CooldownBase)
|
|
13
14
|
CooldownClient.ClassName = "CooldownClient"
|
|
@@ -17,14 +18,18 @@ CooldownClient.__index = CooldownClient
|
|
|
17
18
|
Constructs a new cooldown. Should be done via [CooldownBindersClient]. To create an
|
|
18
19
|
instance of this in Roblox, see [CooldownUtils.create].
|
|
19
20
|
|
|
20
|
-
@param
|
|
21
|
+
@param numberValue NumberValue
|
|
21
22
|
@param serviceBag ServiceBag
|
|
22
23
|
@return Cooldown
|
|
23
24
|
]=]
|
|
24
|
-
function CooldownClient.new(
|
|
25
|
-
local self = setmetatable(CooldownBase.new(
|
|
25
|
+
function CooldownClient.new(numberValue, serviceBag)
|
|
26
|
+
local self = setmetatable(CooldownBase.new(numberValue, serviceBag), CooldownClient)
|
|
27
|
+
|
|
28
|
+
self._maid:GiveTask(self.Done:Connect(function()
|
|
29
|
+
self._obj:Remove()
|
|
30
|
+
end))
|
|
26
31
|
|
|
27
32
|
return self
|
|
28
33
|
end
|
|
29
34
|
|
|
30
|
-
return CooldownClient
|
|
35
|
+
return Binder.new("Cooldown", CooldownClient)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class CooldownServiceClient
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local CooldownServiceClient = {}
|
|
8
|
+
CooldownServiceClient.ServiceName = "CooldownServiceClient"
|
|
9
|
+
|
|
10
|
+
function CooldownServiceClient:Init(serviceBag)
|
|
11
|
+
assert(not self._serviceBag, "Already initialized")
|
|
12
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
13
|
+
|
|
14
|
+
-- External
|
|
15
|
+
self._serviceBag:GetService(require("TimeSyncService"))
|
|
16
|
+
|
|
17
|
+
-- Internal
|
|
18
|
+
self._serviceBag:GetService(require("CooldownClient"))
|
|
19
|
+
self._serviceBag:GetService(require("CooldownShared"))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return CooldownServiceClient
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Represents a cooldown state with a time limit. See [CooldownBase] for more API.
|
|
3
|
+
|
|
4
|
+
@server
|
|
5
|
+
@class Cooldown
|
|
6
|
+
]=]
|
|
7
|
+
|
|
8
|
+
local require = require(script.Parent.loader).load(script)
|
|
9
|
+
|
|
10
|
+
local CooldownBase = require("CooldownBase")
|
|
11
|
+
local TimeSyncService = require("TimeSyncService")
|
|
12
|
+
local CooldownConstants = require("CooldownConstants")
|
|
13
|
+
local AttributeValue = require("AttributeValue")
|
|
14
|
+
local Binder = require("Binder")
|
|
15
|
+
local PropertyValue = require("PropertyValue")
|
|
16
|
+
|
|
17
|
+
local Cooldown = setmetatable({}, CooldownBase)
|
|
18
|
+
Cooldown.ClassName = "Cooldown"
|
|
19
|
+
Cooldown.__index = Cooldown
|
|
20
|
+
|
|
21
|
+
--[=[
|
|
22
|
+
Constructs a new cooldown. Should be done via [Binder].
|
|
23
|
+
|
|
24
|
+
@param numberValue NumberValue
|
|
25
|
+
@param serviceBag ServiceBag
|
|
26
|
+
@return Cooldown
|
|
27
|
+
]=]
|
|
28
|
+
function Cooldown.new(numberValue, serviceBag)
|
|
29
|
+
local self = setmetatable(CooldownBase.new(numberValue, serviceBag), Cooldown)
|
|
30
|
+
|
|
31
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
32
|
+
self._syncedClock = self._serviceBag:GetService(TimeSyncService):GetSyncedClock()
|
|
33
|
+
|
|
34
|
+
self._finishTime = PropertyValue.new(self._obj, "Value")
|
|
35
|
+
self._startTime = AttributeValue.new(self._obj, CooldownConstants.COOLDOWN_START_TIME_ATTRIBUTE, self._syncedClock:GetTime())
|
|
36
|
+
|
|
37
|
+
self._maid:GiveTask(self.Done:Connect(function()
|
|
38
|
+
self._obj:Remove()
|
|
39
|
+
end))
|
|
40
|
+
|
|
41
|
+
return self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
return Binder.new("Cooldown", Cooldown)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class CooldownService
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local CooldownService = {}
|
|
8
|
+
CooldownService.ServiceName = "CooldownService"
|
|
9
|
+
|
|
10
|
+
function CooldownService:Init(serviceBag)
|
|
11
|
+
assert(not self._serviceBag, "Already initialized")
|
|
12
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
13
|
+
|
|
14
|
+
-- External
|
|
15
|
+
self._serviceBag:GetService(require("TimeSyncService"))
|
|
16
|
+
|
|
17
|
+
-- Internal
|
|
18
|
+
self._serviceBag:GetService(require("Cooldown"))
|
|
19
|
+
self._serviceBag:GetService(require("CooldownShared"))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return CooldownService
|
|
@@ -8,7 +8,9 @@ local require = require(script.Parent.loader).load(script)
|
|
|
8
8
|
local BaseObject = require("BaseObject")
|
|
9
9
|
local TimeSyncService = require("TimeSyncService")
|
|
10
10
|
local CooldownConstants = require("CooldownConstants")
|
|
11
|
-
local
|
|
11
|
+
local CooldownModel = require("CooldownModel")
|
|
12
|
+
local RxAttributeUtils = require("RxAttributeUtils")
|
|
13
|
+
local RxInstanceUtils = require("RxInstanceUtils")
|
|
12
14
|
|
|
13
15
|
local CooldownBase = setmetatable({}, BaseObject)
|
|
14
16
|
CooldownBase.ClassName = "CooldownBase"
|
|
@@ -17,35 +19,44 @@ CooldownBase.__index = CooldownBase
|
|
|
17
19
|
--[=[
|
|
18
20
|
Constructs a new Cooldown.
|
|
19
21
|
|
|
20
|
-
@param
|
|
22
|
+
@param numberValue NumberValue
|
|
21
23
|
@param serviceBag ServiceBag
|
|
22
24
|
@return CooldownBase
|
|
23
25
|
]=]
|
|
24
|
-
function CooldownBase.new(
|
|
25
|
-
local self = setmetatable(BaseObject.new(
|
|
26
|
+
function CooldownBase.new(numberValue, serviceBag)
|
|
27
|
+
local self = setmetatable(BaseObject.new(numberValue), CooldownBase)
|
|
26
28
|
|
|
27
29
|
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
28
30
|
self._timeSyncService = self._serviceBag:GetService(TimeSyncService)
|
|
29
31
|
|
|
32
|
+
self._cooldownModel = self._maid:Add(CooldownModel.new())
|
|
30
33
|
self._maid:GivePromise(self._timeSyncService:PromiseSyncedClock())
|
|
31
34
|
:Then(function(syncedClock)
|
|
32
35
|
self._syncedClock = syncedClock
|
|
36
|
+
|
|
37
|
+
-- Setup
|
|
38
|
+
self._cooldownModel:SetStartTime(RxAttributeUtils.observeAttribute(self._obj, CooldownConstants.COOLDOWN_START_TIME_ATTRIBUTE, syncedClock:GetTime()))
|
|
39
|
+
self._cooldownModel:SetLength(RxInstanceUtils.observeProperty(self._obj, "Value"))
|
|
40
|
+
|
|
41
|
+
self._cooldownModel:SetClock(function()
|
|
42
|
+
return self._syncedClock:GetTime()
|
|
43
|
+
end)
|
|
33
44
|
end)
|
|
34
45
|
|
|
35
46
|
--[=[
|
|
36
47
|
Event that fires when the cooldown is done.
|
|
37
48
|
@prop Done Signal<()>
|
|
38
|
-
@within
|
|
49
|
+
@within CooldownBase
|
|
39
50
|
]=]
|
|
40
|
-
self.Done =
|
|
41
|
-
self._maid:GiveTask(function()
|
|
42
|
-
self.Done:Fire()
|
|
43
|
-
self.Done:Destroy()
|
|
44
|
-
end)
|
|
51
|
+
self.Done = assert(self._cooldownModel.Done, "No done signal")
|
|
45
52
|
|
|
46
53
|
return self
|
|
47
54
|
end
|
|
48
55
|
|
|
56
|
+
function CooldownBase:GetCooldownModel()
|
|
57
|
+
return self._cooldownModel
|
|
58
|
+
end
|
|
59
|
+
|
|
49
60
|
--[=[
|
|
50
61
|
Gets the Roblox instance of the cooldown.
|
|
51
62
|
@return Instance
|
|
@@ -59,16 +70,7 @@ end
|
|
|
59
70
|
@return number?
|
|
60
71
|
]=]
|
|
61
72
|
function CooldownBase:GetTimePassed()
|
|
62
|
-
|
|
63
|
-
if not startTime then
|
|
64
|
-
return nil
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
if not self._syncedClock then
|
|
68
|
-
return nil
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
return self._syncedClock:GetTime() - startTime
|
|
73
|
+
return self._cooldownModel:GetTimePassed()
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
--[=[
|
|
@@ -76,16 +78,7 @@ end
|
|
|
76
78
|
@return number?
|
|
77
79
|
]=]
|
|
78
80
|
function CooldownBase:GetTimeRemaining()
|
|
79
|
-
|
|
80
|
-
if not endTime then
|
|
81
|
-
return nil
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
if not self._syncedClock then
|
|
85
|
-
return nil
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
return math.max(0, endTime - self._syncedClock:GetTime())
|
|
81
|
+
return self._cooldownModel:GetTimeRemaining()
|
|
89
82
|
end
|
|
90
83
|
|
|
91
84
|
--[=[
|
|
@@ -93,11 +86,7 @@ end
|
|
|
93
86
|
@return number?
|
|
94
87
|
]=]
|
|
95
88
|
function CooldownBase:GetEndTime()
|
|
96
|
-
|
|
97
|
-
if not startTime then
|
|
98
|
-
return nil
|
|
99
|
-
end
|
|
100
|
-
return startTime + self:GetLength()
|
|
89
|
+
return self._cooldownModel:GetEndTime()
|
|
101
90
|
end
|
|
102
91
|
|
|
103
92
|
--[=[
|
|
@@ -105,12 +94,7 @@ end
|
|
|
105
94
|
@return number?
|
|
106
95
|
]=]
|
|
107
96
|
function CooldownBase:GetStartTime()
|
|
108
|
-
|
|
109
|
-
if type(startTime) == "number" then
|
|
110
|
-
return startTime
|
|
111
|
-
else
|
|
112
|
-
return nil
|
|
113
|
-
end
|
|
97
|
+
return self._cooldownModel:GetStartTime()
|
|
114
98
|
end
|
|
115
99
|
|
|
116
100
|
--[=[
|
|
@@ -118,7 +102,7 @@ end
|
|
|
118
102
|
@return number
|
|
119
103
|
]=]
|
|
120
104
|
function CooldownBase:GetLength()
|
|
121
|
-
return self.
|
|
105
|
+
return self._cooldownModel:GetLength()
|
|
122
106
|
end
|
|
123
107
|
|
|
124
108
|
return CooldownBase
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class CooldownShared
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local CooldownBase = require("CooldownBase")
|
|
8
|
+
local Binder = require("Binder")
|
|
9
|
+
|
|
10
|
+
local CooldownShared = setmetatable({}, CooldownBase)
|
|
11
|
+
CooldownShared.ClassName = "CooldownShared"
|
|
12
|
+
CooldownShared.__index = CooldownShared
|
|
13
|
+
|
|
14
|
+
function CooldownShared.new(numberValue, serviceBag)
|
|
15
|
+
local self = setmetatable(CooldownBase.new(numberValue, serviceBag), CooldownShared)
|
|
16
|
+
|
|
17
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
18
|
+
|
|
19
|
+
return self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return Binder.new("Cooldown", CooldownShared)
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
|
|
6
6
|
local require = require(script.Parent.loader).load(script)
|
|
7
7
|
|
|
8
|
+
local CollectionService = game:GetService("CollectionService")
|
|
9
|
+
|
|
8
10
|
local BinderUtils = require("BinderUtils")
|
|
9
11
|
|
|
10
12
|
local CooldownUtils = {}
|
|
11
13
|
|
|
12
14
|
--[=[
|
|
13
15
|
Creates a new Roblox instance representing a cooldown.
|
|
14
|
-
@param cooldownBinder Binder<Cooldown | CooldownClient>
|
|
15
16
|
@param parent Instance
|
|
16
17
|
@param length number
|
|
17
18
|
@return Instance
|
|
18
19
|
]=]
|
|
19
|
-
function CooldownUtils.create(
|
|
20
|
-
assert(cooldownBinder, "Bad cooldownBinder")
|
|
20
|
+
function CooldownUtils.create(parent, length)
|
|
21
21
|
assert(typeof(parent) == "Instance", "Bad parent")
|
|
22
22
|
assert(type(length) == "number", "Bad length")
|
|
23
23
|
assert(length > 0, "Bad length")
|
|
@@ -26,7 +26,7 @@ function CooldownUtils.create(cooldownBinder, parent, length)
|
|
|
26
26
|
cooldown.Value = length
|
|
27
27
|
cooldown.Name = "Cooldown"
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
CollectionService:AddTag(cooldown, "Cooldown")
|
|
30
30
|
|
|
31
31
|
cooldown.Parent = parent
|
|
32
32
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class CooldownModel
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local BaseObject = require("BaseObject")
|
|
8
|
+
local ValueObject = require("ValueObject")
|
|
9
|
+
local Signal = require("Signal")
|
|
10
|
+
local Rx = require("Rx")
|
|
11
|
+
local DuckTypeUtils = require("DuckTypeUtils")
|
|
12
|
+
|
|
13
|
+
local CooldownModel = setmetatable({}, BaseObject)
|
|
14
|
+
CooldownModel.ClassName = "CooldownModel"
|
|
15
|
+
CooldownModel.__index = CooldownModel
|
|
16
|
+
|
|
17
|
+
function CooldownModel.new()
|
|
18
|
+
local self = setmetatable(BaseObject.new(), CooldownModel)
|
|
19
|
+
|
|
20
|
+
self._length = self._maid:Add(ValueObject.new(0, "number"))
|
|
21
|
+
self._startTime = self._maid:Add(ValueObject.new(os.clock(), "number"))
|
|
22
|
+
self._clock = self._maid:Add(ValueObject.new(os.clock, "function"))
|
|
23
|
+
|
|
24
|
+
do
|
|
25
|
+
self._doneFired = false
|
|
26
|
+
self.Done = Signal.new()
|
|
27
|
+
|
|
28
|
+
self._maid:GiveTask(function()
|
|
29
|
+
if not self._doneFired then
|
|
30
|
+
self._doneFired = true
|
|
31
|
+
self.Done:Fire()
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
self.Done:Destroy()
|
|
35
|
+
end)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
self._maid:GiveTask(Rx.combineLatest({
|
|
39
|
+
length = self._length:Observe();
|
|
40
|
+
clock = self._clock:Observe();
|
|
41
|
+
startTime = self._startTime:Observe();
|
|
42
|
+
}):Pipe({
|
|
43
|
+
Rx.throttleDefer();
|
|
44
|
+
}):Subscribe(function(state)
|
|
45
|
+
local now = state.clock()
|
|
46
|
+
local waitTime = state.length + state.startTime - now
|
|
47
|
+
|
|
48
|
+
if self._doneFired then
|
|
49
|
+
self._maid._cleanup = nil
|
|
50
|
+
else
|
|
51
|
+
self._maid._cleanup = task.delay(waitTime, function()
|
|
52
|
+
self._doneFired = true
|
|
53
|
+
self.Done:Fire()
|
|
54
|
+
end)
|
|
55
|
+
end
|
|
56
|
+
end))
|
|
57
|
+
|
|
58
|
+
return self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
function CooldownModel.isCooldownModel(value)
|
|
62
|
+
return DuckTypeUtils.isImplementation(CooldownModel, value)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
function CooldownModel:SetClock(clock)
|
|
66
|
+
if self._doneFired then
|
|
67
|
+
warn("[CooldownModel] - Done already fired")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
self._clock:Mount(clock)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
function CooldownModel:SetStartTime(startTime)
|
|
74
|
+
if self._doneFired then
|
|
75
|
+
warn("[CooldownModel] - Done already fired")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
self._startTime:Mount(startTime)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
function CooldownModel:SetLength(length)
|
|
82
|
+
if self._doneFired then
|
|
83
|
+
warn("[CooldownModel] - Done already fired")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
self._length:Mount(length)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
--[=[
|
|
90
|
+
Gets the syncronized time stamp the cooldown is starting at
|
|
91
|
+
@return number
|
|
92
|
+
]=]
|
|
93
|
+
function CooldownModel:GetStartTime()
|
|
94
|
+
return self._startTime.Value
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
--[=[
|
|
98
|
+
Gets the time remaining
|
|
99
|
+
@return number
|
|
100
|
+
]=]
|
|
101
|
+
function CooldownModel:GetTimeRemaining()
|
|
102
|
+
local endTime = self:GetEndTime()
|
|
103
|
+
|
|
104
|
+
return math.max(0, endTime - self._clock.Value())
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
function CooldownModel:GetTimePassed()
|
|
108
|
+
local startTime = self._startTime.Value
|
|
109
|
+
return self._clock.Value() - startTime
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
--[=[
|
|
113
|
+
Gets the syncronized time stamp the cooldown is ending at
|
|
114
|
+
@return number?
|
|
115
|
+
]=]
|
|
116
|
+
function CooldownModel:GetEndTime()
|
|
117
|
+
return self._startTime.Value + self:GetLength()
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
function CooldownModel:GetLength()
|
|
121
|
+
return self._length.Value
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
return CooldownModel
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class CooldownTrackerModel
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local BaseObject = require("BaseObject")
|
|
8
|
+
local ValueObject = require("ValueObject")
|
|
9
|
+
local DuckTypeUtils = require("DuckTypeUtils")
|
|
10
|
+
|
|
11
|
+
local CooldownTrackerModel = setmetatable({}, BaseObject)
|
|
12
|
+
CooldownTrackerModel.ClassName = "CooldownTrackerModel"
|
|
13
|
+
CooldownTrackerModel.__index = CooldownTrackerModel
|
|
14
|
+
|
|
15
|
+
function CooldownTrackerModel.new()
|
|
16
|
+
local self = setmetatable(BaseObject.new(), CooldownTrackerModel)
|
|
17
|
+
|
|
18
|
+
self._currentCooldownModel = self._maid:Add(ValueObject.new(nil))
|
|
19
|
+
|
|
20
|
+
self._maid:GiveTask(self._currentCooldownModel:ObserveBrio(function(value)
|
|
21
|
+
return value ~= nil
|
|
22
|
+
end):Subscribe(function(brio)
|
|
23
|
+
if brio:IsDead() then
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
local maid, cooldown = brio:ToMaidAndValue()
|
|
28
|
+
maid:GiveTask(cooldown.Done:Connect(function()
|
|
29
|
+
if self._currentCooldownModel.Value == cooldown then
|
|
30
|
+
self._currentCooldownModel.Value = nil
|
|
31
|
+
end
|
|
32
|
+
end))
|
|
33
|
+
end))
|
|
34
|
+
|
|
35
|
+
return self
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
function CooldownTrackerModel.isCooldownTrackerModel(value)
|
|
39
|
+
return DuckTypeUtils.isImplementation(CooldownTrackerModel, value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
function CooldownTrackerModel:IsCoolingDown()
|
|
43
|
+
return self._currentCooldownModel.Value ~= nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
function CooldownTrackerModel:ObserveActiveCooldownModel()
|
|
47
|
+
return self._currentCooldownModel:Observe()
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
function CooldownTrackerModel:ObserveActiveCooldownModelBrio()
|
|
51
|
+
return self._currentCooldownModel:ObserveBrio(function(value)
|
|
52
|
+
return value ~= nil
|
|
53
|
+
end)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
function CooldownTrackerModel:SetCooldownModel(cooldownModel)
|
|
57
|
+
self._currentCooldownModel:Mount(cooldownModel)
|
|
58
|
+
|
|
59
|
+
return function()
|
|
60
|
+
if not self.Destroy then
|
|
61
|
+
return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
if self._currentCooldownModel.Value == cooldownModel then
|
|
65
|
+
self._currentCooldownModel.Value = nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
return CooldownTrackerModel
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Tracks current cooldown on an object
|
|
3
|
+
@class CooldownTracker
|
|
4
|
+
]=]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local BaseObject = require("BaseObject")
|
|
9
|
+
local CooldownShared = require("CooldownShared")
|
|
10
|
+
local ValueObject = require("ValueObject")
|
|
11
|
+
local RxBinderUtils = require("RxBinderUtils")
|
|
12
|
+
local CooldownTrackerModel = require("CooldownTrackerModel")
|
|
13
|
+
|
|
14
|
+
local CooldownTracker = setmetatable({}, BaseObject)
|
|
15
|
+
CooldownTracker.ClassName = "CooldownTracker"
|
|
16
|
+
CooldownTracker.__index = CooldownTracker
|
|
17
|
+
|
|
18
|
+
function CooldownTracker.new(serviceBag, parent)
|
|
19
|
+
assert(typeof(parent) == "Instance", "Bad parent")
|
|
20
|
+
|
|
21
|
+
local self = setmetatable(BaseObject.new(parent), CooldownTracker)
|
|
22
|
+
|
|
23
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
24
|
+
self._cooldownBinder = self._serviceBag:GetService(CooldownShared)
|
|
25
|
+
|
|
26
|
+
self.CurrentCooldown = self._maid:Add(ValueObject.new(nil))
|
|
27
|
+
self._cooldownTrackModel = self._maid:Add(CooldownTrackerModel.new())
|
|
28
|
+
|
|
29
|
+
self._maid:GiveTask(self.CurrentCooldown.Changed:Connect(function(...)
|
|
30
|
+
self:_handleNewCooldown(...)
|
|
31
|
+
end))
|
|
32
|
+
|
|
33
|
+
-- Handle not running
|
|
34
|
+
self._maid:GiveTask(RxBinderUtils.observeBoundChildClassBrio(self._cooldownBinder, self._obj)
|
|
35
|
+
:Subscribe(function(brio)
|
|
36
|
+
if brio:IsDead() then
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
-- TODO: Use stack (with multiple cooldowns)
|
|
41
|
+
local cooldown = brio:GetValue()
|
|
42
|
+
local maid = brio:ToMaid()
|
|
43
|
+
|
|
44
|
+
maid:GiveTask(self._cooldownTrackModel:SetCooldownModel(cooldown:GetCooldownModel()))
|
|
45
|
+
|
|
46
|
+
self.CurrentCooldown.Value = cooldown
|
|
47
|
+
|
|
48
|
+
maid:GiveTask(function()
|
|
49
|
+
if not self.Destroy then
|
|
50
|
+
return
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if self.CurrentCooldown.Value == cooldown then
|
|
54
|
+
self._cooldownTrackModel:SetCooldownModel(nil)
|
|
55
|
+
self.CurrentCooldown.Value = nil
|
|
56
|
+
end
|
|
57
|
+
end)
|
|
58
|
+
end))
|
|
59
|
+
|
|
60
|
+
return self
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
function CooldownTracker:GetCooldownTrackerModel()
|
|
64
|
+
return self._cooldownTrackModel
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
function CooldownTracker:IsCoolingDown()
|
|
68
|
+
return self._cooldownTrackModel:IsCoolingDown()
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
function CooldownTracker:_handleNewCooldown(new, _old, maid)
|
|
72
|
+
if new then
|
|
73
|
+
maid:GiveTask(new.Done:Connect(function()
|
|
74
|
+
if self.CurrentCooldown.Value == new then
|
|
75
|
+
self.CurrentCooldown.Value = nil
|
|
76
|
+
end
|
|
77
|
+
end))
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return CooldownTracker
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Holds binders for [Cooldown].
|
|
3
|
-
@class CooldownBindersClient
|
|
4
|
-
]=]
|
|
5
|
-
|
|
6
|
-
local require = require(script.Parent.loader).load(script)
|
|
7
|
-
|
|
8
|
-
local BinderProvider = require("BinderProvider")
|
|
9
|
-
local Binder = require("Binder")
|
|
10
|
-
local TimeSyncService = require("TimeSyncService")
|
|
11
|
-
|
|
12
|
-
return BinderProvider.new(script.Name, function(self, serviceBag)
|
|
13
|
-
serviceBag:GetService(TimeSyncService)
|
|
14
|
-
|
|
15
|
-
--[=[
|
|
16
|
-
@prop Cooldown Binder<CooldownClient>
|
|
17
|
-
@within CooldownBindersClient
|
|
18
|
-
]=]
|
|
19
|
-
self:Add(Binder.new("Cooldown", require("CooldownClient"), serviceBag))
|
|
20
|
-
end)
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Tracks current cooldown on an object
|
|
3
|
-
@class CooldownTracker
|
|
4
|
-
]=]
|
|
5
|
-
|
|
6
|
-
local require = require(script.Parent.loader).load(script)
|
|
7
|
-
|
|
8
|
-
local BaseObject = require("BaseObject")
|
|
9
|
-
local CooldownBindersClient = require("CooldownBindersClient")
|
|
10
|
-
local ValueObject = require("ValueObject")
|
|
11
|
-
local RxBinderUtils = require("RxBinderUtils")
|
|
12
|
-
|
|
13
|
-
local CooldownTracker = setmetatable({}, BaseObject)
|
|
14
|
-
CooldownTracker.ClassName = "CooldownTracker"
|
|
15
|
-
CooldownTracker.__index = CooldownTracker
|
|
16
|
-
|
|
17
|
-
function CooldownTracker.new(serviceBag, parent)
|
|
18
|
-
local self = setmetatable(BaseObject.new(parent), CooldownTracker)
|
|
19
|
-
|
|
20
|
-
assert(parent, "No parent")
|
|
21
|
-
|
|
22
|
-
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
23
|
-
self._cooldownBinders = self._serviceBag:GetService(CooldownBindersClient)
|
|
24
|
-
|
|
25
|
-
self.CurrentCooldown = ValueObject.new()
|
|
26
|
-
self._maid:GiveTask(self.CurrentCooldown)
|
|
27
|
-
|
|
28
|
-
self._maid:GiveTask(self.CurrentCooldown.Changed:Connect(function(...)
|
|
29
|
-
self:_handleNewCooldown(...)
|
|
30
|
-
end))
|
|
31
|
-
|
|
32
|
-
-- Handle not running
|
|
33
|
-
self._maid:GivePromise(self._cooldownBinders:PromiseBinder("Cooldown"))
|
|
34
|
-
:Then(function(cooldownBinder)
|
|
35
|
-
self._maid:GiveTask(RxBinderUtils.observeBoundChildClassBrio(cooldownBinder, self._obj)
|
|
36
|
-
:Subscribe(function(brio)
|
|
37
|
-
if brio:IsDead() then
|
|
38
|
-
return
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
-- TODO: Use stack (with multiple cooldowns)
|
|
42
|
-
local cooldown = brio:GetValue()
|
|
43
|
-
local maid = brio:ToMaid()
|
|
44
|
-
self.CurrentCooldown.Value = cooldown
|
|
45
|
-
|
|
46
|
-
maid:GiveTask(function()
|
|
47
|
-
if self.CurrentCooldown.Value == cooldown then
|
|
48
|
-
self.CurrentCooldown.Value = nil
|
|
49
|
-
end
|
|
50
|
-
end)
|
|
51
|
-
end))
|
|
52
|
-
end)
|
|
53
|
-
|
|
54
|
-
return self
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
function CooldownTracker:_handleNewCooldown(new, _old, maid)
|
|
58
|
-
if new then
|
|
59
|
-
maid:GiveTask(new.Done:Connect(function()
|
|
60
|
-
if self.CurrentCooldown.Value == new then
|
|
61
|
-
self.CurrentCooldown.Value = nil
|
|
62
|
-
end
|
|
63
|
-
end))
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
return CooldownTracker
|
package/src/Server/Cooldown.lua
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Represents a cooldown state with a time limit. See [CooldownBase] for more API.
|
|
3
|
-
|
|
4
|
-
@server
|
|
5
|
-
@class Cooldown
|
|
6
|
-
]=]
|
|
7
|
-
|
|
8
|
-
local require = require(script.Parent.loader).load(script)
|
|
9
|
-
|
|
10
|
-
local CooldownBase = require("CooldownBase")
|
|
11
|
-
local TimeSyncService = require("TimeSyncService")
|
|
12
|
-
local CooldownConstants = require("CooldownConstants")
|
|
13
|
-
local AttributeUtils = require("AttributeUtils")
|
|
14
|
-
|
|
15
|
-
local Cooldown = setmetatable({}, CooldownBase)
|
|
16
|
-
Cooldown.ClassName = "Cooldown"
|
|
17
|
-
Cooldown.__index = Cooldown
|
|
18
|
-
|
|
19
|
-
--[=[
|
|
20
|
-
Constructs a new cooldown. Should be done via [CooldownBindersServer]. To create an
|
|
21
|
-
instance of this in Roblox, see [CooldownUtils.create].
|
|
22
|
-
|
|
23
|
-
@param obj NumberValue
|
|
24
|
-
@param serviceBag ServiceBag
|
|
25
|
-
@return Cooldown
|
|
26
|
-
]=]
|
|
27
|
-
function Cooldown.new(obj, serviceBag)
|
|
28
|
-
local self = setmetatable(CooldownBase.new(obj, serviceBag), Cooldown)
|
|
29
|
-
|
|
30
|
-
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
31
|
-
|
|
32
|
-
local now = self._serviceBag:GetService(TimeSyncService):GetSyncedClock():GetTime()
|
|
33
|
-
local startTime = AttributeUtils.initAttribute(self._obj, CooldownConstants.COOLDOWN_START_TIME_ATTRIBUTE, now)
|
|
34
|
-
|
|
35
|
-
-- Delay for cooldown time
|
|
36
|
-
-- TODO: Handle start tme changing
|
|
37
|
-
task.delay(self._obj.Value + startTime - now, function()
|
|
38
|
-
if self.Destroy then
|
|
39
|
-
self._obj:Destroy()
|
|
40
|
-
end
|
|
41
|
-
end)
|
|
42
|
-
|
|
43
|
-
return self
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
return Cooldown
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Holds binders for [Cooldown].
|
|
3
|
-
@class CooldownBindersServer
|
|
4
|
-
]=]
|
|
5
|
-
|
|
6
|
-
local require = require(script.Parent.loader).load(script)
|
|
7
|
-
|
|
8
|
-
local BinderProvider = require("BinderProvider")
|
|
9
|
-
local Binder = require("Binder")
|
|
10
|
-
local TimeSyncService = require("TimeSyncService")
|
|
11
|
-
|
|
12
|
-
return BinderProvider.new(script.Name, function(self, serviceBag)
|
|
13
|
-
serviceBag:GetService(TimeSyncService)
|
|
14
|
-
|
|
15
|
-
--[=[
|
|
16
|
-
@prop Cooldown Binder<Cooldown>
|
|
17
|
-
@within CooldownBindersServer
|
|
18
|
-
]=]
|
|
19
|
-
self:Add(Binder.new("Cooldown", require("Cooldown"), serviceBag))
|
|
20
|
-
end)
|