@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 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-canary.367.e9fdcbc.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/cooldown@5.21.0...@quenty/cooldown@6.0.0-canary.367.e9fdcbc.0) (2023-06-05)
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-canary.367.e9fdcbc.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": "8.15.0",
29
- "@quenty/baseobject": "6.2.1",
30
- "@quenty/binder": "9.0.0-canary.367.e9fdcbc.0",
31
- "@quenty/loader": "6.2.1",
32
- "@quenty/maid": "2.5.0",
33
- "@quenty/promise": "6.5.0",
34
- "@quenty/remoting": "6.5.0",
35
- "@quenty/rxbinderutils": "9.0.0-canary.367.e9fdcbc.0",
36
- "@quenty/servicebag": "6.7.0",
37
- "@quenty/signal": "2.4.0",
38
- "@quenty/table": "3.2.0",
39
- "@quenty/timesyncservice": "7.7.0",
40
- "@quenty/valueobject": "8.0.0-canary.367.e9fdcbc.0"
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": "e9fdcbc6ea1d46e068bf42a08b833099e9005259"
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 obj NumberValue
21
+ @param numberValue NumberValue
21
22
  @param serviceBag ServiceBag
22
23
  @return Cooldown
23
24
  ]=]
24
- function CooldownClient.new(obj, serviceBag)
25
- local self = setmetatable(CooldownBase.new(obj, serviceBag), CooldownClient)
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 Signal = require("Signal")
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 obj NumberValue
22
+ @param numberValue NumberValue
21
23
  @param serviceBag ServiceBag
22
24
  @return CooldownBase
23
25
  ]=]
24
- function CooldownBase.new(obj, serviceBag)
25
- local self = setmetatable(BaseObject.new(obj), CooldownBase)
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 CooldownClient
49
+ @within CooldownBase
39
50
  ]=]
40
- self.Done = Signal.new()
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
- local startTime = self:GetStartTime()
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
- local endTime = self:GetEndTime()
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
- local startTime = self:GetStartTime()
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
- local startTime = self._obj:GetAttribute(CooldownConstants.COOLDOWN_START_TIME_ATTRIBUTE)
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._obj.Value
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(cooldownBinder, parent, length)
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
- cooldownBinder:Bind(cooldown)
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
@@ -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)