@quenty/rogue-properties 11.25.1 → 11.25.2-canary.63ba0e0.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 +19 -0
- package/package.json +27 -25
- package/src/Shared/Array/RoguePropertyArrayUtils.lua +7 -0
- package/src/Shared/Definition/RoguePropertyDefinition.lua +15 -1
- package/src/Shared/Definition/RoguePropertyTableDefinition.lua +27 -40
- package/src/Shared/Implementation/RogueProperty.lua +337 -105
- package/src/Shared/Implementation/RoguePropertyArrayHelper.lua +14 -2
- package/src/Shared/Implementation/RoguePropertyTable.lua +78 -14
- package/src/Shared/RoguePropertyBaseValueTypeUtils.lua +15 -0
- package/src/Shared/RoguePropertyBaseValueTypes.lua +12 -0
- package/src/Shared/RoguePropertyConstants.lua +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
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
|
+
## [11.25.2-canary.63ba0e0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rogue-properties@11.25.1...@quenty/rogue-properties@11.25.2-canary.63ba0e0.0) (2025-09-26)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Fix caching performance of the rogue system when multiple things want to observe state ([1a067f7](https://github.com/Quenty/NevermoreEngine/commit/1a067f7dec837a2eb4db399e46bf06566824c9a3))
|
|
12
|
+
* Fix parenting and application on client ([ff2f125](https://github.com/Quenty/NevermoreEngine/commit/ff2f1254f45289537444190bc0596f9f519c592e))
|
|
13
|
+
* Fix stuff ([63ba0e0](https://github.com/Quenty/NevermoreEngine/commit/63ba0e0c4b5c8bdaeb452f0b3d742b7b8bc8a7ab))
|
|
14
|
+
* Style stuff ([ff3c47a](https://github.com/Quenty/NevermoreEngine/commit/ff3c47af4e5b23f912aa09a0784849751d5736e1))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* Move the rogue properties over to attributes as required ([4aa23b0](https://github.com/Quenty/NevermoreEngine/commit/4aa23b0092ba07490b615f1d8ab5920f86b78756))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
## [11.25.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rogue-properties@11.25.0...@quenty/rogue-properties@11.25.1) (2025-09-15)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @quenty/rogue-properties
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/rogue-properties",
|
|
3
|
-
"version": "11.25.
|
|
3
|
+
"version": "11.25.2-canary.63ba0e0.0",
|
|
4
4
|
"description": "Roguelike properties which can be modified by external provides",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -24,33 +24,35 @@
|
|
|
24
24
|
"Quenty"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@quenty/adorneedata": "
|
|
28
|
-
"@quenty/
|
|
29
|
-
"@quenty/
|
|
30
|
-
"@quenty/
|
|
31
|
-
"@quenty/
|
|
32
|
-
"@quenty/
|
|
33
|
-
"@quenty/
|
|
34
|
-
"@quenty/
|
|
35
|
-
"@quenty/
|
|
36
|
-
"@quenty/
|
|
37
|
-
"@quenty/
|
|
38
|
-
"@quenty/
|
|
39
|
-
"@quenty/
|
|
40
|
-
"@quenty/
|
|
41
|
-
"@quenty/
|
|
42
|
-
"@quenty/
|
|
43
|
-
"@quenty/
|
|
44
|
-
"@quenty/
|
|
45
|
-
"@quenty/
|
|
46
|
-
"@quenty/
|
|
47
|
-
"@quenty/
|
|
48
|
-
"@quenty/
|
|
49
|
-
"@quenty/
|
|
27
|
+
"@quenty/adorneedata": "7.20.1-canary.63ba0e0.0",
|
|
28
|
+
"@quenty/attributeutils": "14.19.1-canary.63ba0e0.0",
|
|
29
|
+
"@quenty/baseobject": "10.9.0",
|
|
30
|
+
"@quenty/binder": "14.22.1-canary.63ba0e0.0",
|
|
31
|
+
"@quenty/brio": "14.19.1-canary.63ba0e0.0",
|
|
32
|
+
"@quenty/defaultvalueutils": "1.2.2",
|
|
33
|
+
"@quenty/ducktype": "5.9.0",
|
|
34
|
+
"@quenty/instanceutils": "13.19.1-canary.63ba0e0.0",
|
|
35
|
+
"@quenty/jsonutils": "10.12.0",
|
|
36
|
+
"@quenty/linkutils": "13.19.1-canary.63ba0e0.0",
|
|
37
|
+
"@quenty/loader": "10.9.0",
|
|
38
|
+
"@quenty/maid": "3.5.0",
|
|
39
|
+
"@quenty/observablecollection": "12.22.2-canary.63ba0e0.0",
|
|
40
|
+
"@quenty/remoting": "12.20.1-canary.63ba0e0.0",
|
|
41
|
+
"@quenty/rx": "13.19.1-canary.63ba0e0.0",
|
|
42
|
+
"@quenty/rxbinderutils": "14.22.1-canary.63ba0e0.0",
|
|
43
|
+
"@quenty/rxsignal": "7.19.1-canary.63ba0e0.0",
|
|
44
|
+
"@quenty/servicebag": "11.13.1",
|
|
45
|
+
"@quenty/signal": "7.11.1",
|
|
46
|
+
"@quenty/spring": "10.9.0",
|
|
47
|
+
"@quenty/string": "3.3.3",
|
|
48
|
+
"@quenty/table": "3.8.0",
|
|
49
|
+
"@quenty/tie": "10.22.1-canary.63ba0e0.0",
|
|
50
|
+
"@quenty/valuebaseutils": "13.19.1-canary.63ba0e0.0",
|
|
51
|
+
"@quenty/valueobject": "13.19.1-canary.63ba0e0.0",
|
|
50
52
|
"@quentystudios/t": "^3.0.0"
|
|
51
53
|
},
|
|
52
54
|
"publishConfig": {
|
|
53
55
|
"access": "public"
|
|
54
56
|
},
|
|
55
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "63ba0e0c4b5c8bdaeb452f0b3d742b7b8bc8a7ab"
|
|
56
58
|
}
|
|
@@ -114,6 +114,13 @@ end
|
|
|
114
114
|
function RoguePropertyArrayUtils.getDefaultValueMapFromContainer(container: Instance)
|
|
115
115
|
local value = {}
|
|
116
116
|
|
|
117
|
+
-- This is a hack, kinda
|
|
118
|
+
for attributeKey, attributeValue in container:GetAttributes() do
|
|
119
|
+
if attributeKey ~= "HasInitializedArrayComponent" then
|
|
120
|
+
value[attributeKey] = attributeValue
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
117
124
|
for _, item in container:GetChildren() do
|
|
118
125
|
local index = RoguePropertyArrayUtils.getIndexFromName(item.Name)
|
|
119
126
|
if index then
|
|
@@ -7,6 +7,7 @@ local require = require(script.Parent.loader).load(script)
|
|
|
7
7
|
local DuckTypeUtils = require("DuckTypeUtils")
|
|
8
8
|
local RogueProperty = require("RogueProperty")
|
|
9
9
|
local RoguePropertyCacheService = require("RoguePropertyCacheService")
|
|
10
|
+
local RoguePropertyConstants = require("RoguePropertyConstants")
|
|
10
11
|
local RoguePropertyUtils = require("RoguePropertyUtils")
|
|
11
12
|
local ServiceBag = require("ServiceBag")
|
|
12
13
|
local ValueBaseUtils = require("ValueBaseUtils")
|
|
@@ -36,6 +37,10 @@ function RoguePropertyDefinition.isRoguePropertyDefinition(value: any): boolean
|
|
|
36
37
|
return DuckTypeUtils.isImplementation(RoguePropertyDefinition, value)
|
|
37
38
|
end
|
|
38
39
|
|
|
40
|
+
function RoguePropertyDefinition:HasChildren(): boolean
|
|
41
|
+
return false
|
|
42
|
+
end
|
|
43
|
+
|
|
39
44
|
--[=[
|
|
40
45
|
@param serviceBag ServiceBag
|
|
41
46
|
@param adornee Instance
|
|
@@ -61,12 +66,21 @@ end
|
|
|
61
66
|
function RoguePropertyDefinition:GetOrCreateInstance(parent: Instance)
|
|
62
67
|
assert(typeof(parent) == "Instance", "Bad parent")
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
-- Note, in forcing the creation, we move to an attribute
|
|
70
|
+
local original = parent:GetAttribute(self:GetName())
|
|
71
|
+
local created = ValueBaseUtils.getOrCreateValue(
|
|
65
72
|
parent,
|
|
66
73
|
self:GetStorageInstanceType(),
|
|
67
74
|
self:GetName(),
|
|
68
75
|
self:GetEncodedDefaultValue()
|
|
69
76
|
)
|
|
77
|
+
|
|
78
|
+
if original ~= nil and original ~= RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE then
|
|
79
|
+
created.Value = original
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
parent:SetAttribute(self:GetName(), RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE)
|
|
83
|
+
return created
|
|
70
84
|
end
|
|
71
85
|
|
|
72
86
|
function RoguePropertyDefinition:SetParentPropertyTableDefinition(parentPropertyTableDefinition)
|
|
@@ -12,8 +12,6 @@ local RoguePropertyDefinition = require("RoguePropertyDefinition")
|
|
|
12
12
|
local RoguePropertyDefinitionArrayHelper = require("RoguePropertyDefinitionArrayHelper")
|
|
13
13
|
local RoguePropertyService = require("RoguePropertyService")
|
|
14
14
|
local RoguePropertyTable = require("RoguePropertyTable")
|
|
15
|
-
local RxBrioUtils = require("RxBrioUtils")
|
|
16
|
-
local RxInstanceUtils = require("RxInstanceUtils")
|
|
17
15
|
local ServiceBag = require("ServiceBag")
|
|
18
16
|
local Set = require("Set")
|
|
19
17
|
local Table = require("Table")
|
|
@@ -133,6 +131,11 @@ function RoguePropertyTableDefinition:CanAssign(mainValue, strict: boolean): (bo
|
|
|
133
131
|
return false, string.format("Bad index %q, %q is not an array", tostring(key), self:GetFullName())
|
|
134
132
|
end
|
|
135
133
|
else
|
|
134
|
+
if self._arrayDefinitionHelper then
|
|
135
|
+
-- TODO: Maybe this check is actually wrong...? we might need to remove it.
|
|
136
|
+
return false, string.format("Bad index %q, %q is an array", tostring(key), self:GetFullName())
|
|
137
|
+
end
|
|
138
|
+
|
|
136
139
|
if self._definitionMap[key] then
|
|
137
140
|
local canAssign, message = self._definitionMap[key]:CanAssign(value, strict)
|
|
138
141
|
if not canAssign then
|
|
@@ -176,6 +179,10 @@ function RoguePropertyTableDefinition:GetDefinitionMap()
|
|
|
176
179
|
return self._definitionMap
|
|
177
180
|
end
|
|
178
181
|
|
|
182
|
+
function RoguePropertyTableDefinition:HasChildren()
|
|
183
|
+
return true
|
|
184
|
+
end
|
|
185
|
+
|
|
179
186
|
--[=[
|
|
180
187
|
Gets the RoguePropertyDefinition if it exists
|
|
181
188
|
@param propertyName
|
|
@@ -223,59 +230,39 @@ RoguePropertyTableDefinition.GetPropertyTable = RoguePropertyTableDefinition.Get
|
|
|
223
230
|
--[=[
|
|
224
231
|
Observes the current container while it exists for the given adornee.
|
|
225
232
|
|
|
226
|
-
@param adornee Instance
|
|
227
|
-
@param canInitialize boolean
|
|
228
233
|
@return Observable<Brio<Folder>>
|
|
229
234
|
]=]
|
|
230
|
-
function RoguePropertyTableDefinition:ObserveContainerBrio(adornee: Instance
|
|
235
|
+
function RoguePropertyTableDefinition:ObserveContainerBrio(serviceBag: ServiceBag.ServiceBag, adornee: Instance)
|
|
236
|
+
assert(serviceBag, "No serviceBag")
|
|
231
237
|
assert(typeof(adornee) == "Instance", "Bad adornee")
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if parentDefinition then
|
|
239
|
-
return parentDefinition:ObserveContainerBrio(adornee, canInitialize):Pipe({
|
|
240
|
-
RxBrioUtils.switchMapBrio(function(parent)
|
|
241
|
-
return RxInstanceUtils.observeLastNamedChildBrio(parent, "Folder", self:GetName())
|
|
242
|
-
end),
|
|
243
|
-
})
|
|
244
|
-
else
|
|
245
|
-
return RxInstanceUtils.observeLastNamedChildBrio(adornee, "Folder", self:GetName())
|
|
246
|
-
end
|
|
238
|
+
|
|
239
|
+
local found = self:Get(serviceBag, adornee)
|
|
240
|
+
|
|
241
|
+
-- TODO: caninitialize is broken
|
|
242
|
+
|
|
243
|
+
return found:ObserveContainerBrio()
|
|
247
244
|
end
|
|
248
245
|
|
|
249
246
|
--[=[
|
|
250
247
|
Gets the current container for the given adornee.
|
|
251
|
-
@param adornee Instance
|
|
252
|
-
@param canInitialize boolean
|
|
253
248
|
@return Folder?
|
|
254
249
|
]=]
|
|
255
|
-
function RoguePropertyTableDefinition:GetContainer(adornee: Instance
|
|
250
|
+
function RoguePropertyTableDefinition:GetContainer(serviceBag: ServiceBag.ServiceBag, adornee: Instance): Folder?
|
|
251
|
+
assert(serviceBag, "No serviceBag")
|
|
256
252
|
assert(typeof(adornee) == "Instance", "Bad adornee")
|
|
257
|
-
assert(type(canInitialize) == "boolean", "Bad canInitialize")
|
|
258
253
|
|
|
259
|
-
local
|
|
260
|
-
local parentDefinition = self:GetParentPropertyDefinition()
|
|
261
|
-
if parentDefinition then
|
|
262
|
-
parent = parentDefinition:GetContainer(adornee, canInitialize)
|
|
263
|
-
else
|
|
264
|
-
parent = adornee
|
|
265
|
-
end
|
|
254
|
+
local found = self:Get(serviceBag, adornee)
|
|
266
255
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
end
|
|
256
|
+
return found:GetContainer()
|
|
257
|
+
end
|
|
270
258
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
end
|
|
259
|
+
function RoguePropertyTableDefinition:FindInstance(parent): Instance?
|
|
260
|
+
assert(typeof(parent) == "Instance", "Bad parent")
|
|
261
|
+
|
|
262
|
+
return parent:FindFirstChild(self:GetName())
|
|
276
263
|
end
|
|
277
264
|
|
|
278
|
-
function RoguePropertyTableDefinition:GetOrCreateInstance(parent)
|
|
265
|
+
function RoguePropertyTableDefinition:GetOrCreateInstance(parent): Folder
|
|
279
266
|
assert(typeof(parent) == "Instance", "Bad parent")
|
|
280
267
|
|
|
281
268
|
local existing = parent:FindFirstChild(self:GetName())
|
|
@@ -4,22 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
local require = require(script.Parent.loader).load(script)
|
|
6
6
|
|
|
7
|
+
local AttributeValue = require("AttributeValue")
|
|
7
8
|
local Maid = require("Maid")
|
|
8
9
|
local Observable = require("Observable")
|
|
9
10
|
local ObservableSortedList = require("ObservableSortedList")
|
|
10
11
|
local RogueAdditive = require("RogueAdditive")
|
|
11
12
|
local RogueModifierInterface = require("RogueModifierInterface")
|
|
12
13
|
local RogueMultiplier = require("RogueMultiplier")
|
|
14
|
+
local RoguePropertyBaseValueTypeUtils = require("RoguePropertyBaseValueTypeUtils")
|
|
15
|
+
local RoguePropertyBaseValueTypes = require("RoguePropertyBaseValueTypes")
|
|
16
|
+
local RoguePropertyConstants = require("RoguePropertyConstants")
|
|
13
17
|
local RoguePropertyModifierData = require("RoguePropertyModifierData")
|
|
14
18
|
local RoguePropertyUtils = require("RoguePropertyUtils")
|
|
15
19
|
local RogueSetter = require("RogueSetter")
|
|
16
20
|
local Rx = require("Rx")
|
|
21
|
+
local RxAttributeUtils = require("RxAttributeUtils")
|
|
17
22
|
local RxBrioUtils = require("RxBrioUtils")
|
|
18
23
|
local RxInstanceUtils = require("RxInstanceUtils")
|
|
19
24
|
local RxSignal = require("RxSignal")
|
|
20
25
|
local ServiceBag = require("ServiceBag")
|
|
26
|
+
local TieRealmService = require("TieRealmService")
|
|
21
27
|
local ValueBaseUtils = require("ValueBaseUtils")
|
|
22
28
|
|
|
29
|
+
local ONLY_USE_INSTANCES = false
|
|
30
|
+
local LOCAL_MODIFIER_CONTAINER_CLASS_NAME = "Camera"
|
|
31
|
+
|
|
23
32
|
local RogueProperty = {}
|
|
24
33
|
RogueProperty.ClassName = "RogueProperty"
|
|
25
34
|
RogueProperty.__index = RogueProperty
|
|
@@ -28,6 +37,7 @@ function RogueProperty.new(adornee: Instance, serviceBag: ServiceBag.ServiceBag,
|
|
|
28
37
|
local self = {}
|
|
29
38
|
|
|
30
39
|
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
40
|
+
self._tieRealmService = self._serviceBag:GetService(TieRealmService)
|
|
31
41
|
|
|
32
42
|
self._adornee = assert(adornee, "Bad adornee")
|
|
33
43
|
self._definition = assert(definition, "Bad definition")
|
|
@@ -43,7 +53,7 @@ function RogueProperty:SetCanInitialize(canInitialize: boolean)
|
|
|
43
53
|
rawset(self, "_canInitialize", canInitialize)
|
|
44
54
|
|
|
45
55
|
if canInitialize then
|
|
46
|
-
self:GetBaseValueObject()
|
|
56
|
+
self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
47
57
|
end
|
|
48
58
|
end
|
|
49
59
|
end
|
|
@@ -56,66 +66,126 @@ function RogueProperty:CanInitialize()
|
|
|
56
66
|
return rawget(self, "_canInitialize")
|
|
57
67
|
end
|
|
58
68
|
|
|
59
|
-
function RogueProperty:
|
|
60
|
-
local
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return cached
|
|
69
|
+
function RogueProperty:_getParentContainer()
|
|
70
|
+
local parentDefinition = self._definition:GetParentPropertyDefinition()
|
|
71
|
+
if parentDefinition then
|
|
72
|
+
return parentDefinition:Get(self._serviceBag, self._adornee):GetContainer()
|
|
73
|
+
else
|
|
74
|
+
return self._adornee
|
|
66
75
|
end
|
|
76
|
+
end
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
function RogueProperty:GetBaseValueObject(roguePropertyBaseValueType)
|
|
79
|
+
assert(
|
|
80
|
+
RoguePropertyBaseValueTypeUtils.isRoguePropertyBaseValueType(roguePropertyBaseValueType),
|
|
81
|
+
"Bad roguePropertyBaseValueType"
|
|
82
|
+
)
|
|
70
83
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
-- TODO: check this caching!
|
|
85
|
+
local cachedInstance = rawget(self, "_baseValueInstanceCache")
|
|
86
|
+
local adornee = rawget(self, "_adornee")
|
|
87
|
+
|
|
88
|
+
if cachedInstance then
|
|
89
|
+
if cachedInstance:IsDescendantOf(adornee) then
|
|
90
|
+
return cachedInstance
|
|
91
|
+
else
|
|
92
|
+
rawset(self, "_baseValueInstanceCache", nil)
|
|
93
|
+
end
|
|
75
94
|
end
|
|
76
95
|
|
|
96
|
+
local definition = rawget(self, "_definition")
|
|
97
|
+
|
|
98
|
+
local parent = self:_getParentContainer()
|
|
77
99
|
if not parent then
|
|
78
100
|
return nil
|
|
79
101
|
end
|
|
80
102
|
|
|
103
|
+
local currentAttribute = parent:GetAttribute(definition:GetName())
|
|
104
|
+
local instanceRequired = roguePropertyBaseValueType == RoguePropertyBaseValueTypes.INSTANCE
|
|
105
|
+
or definition:HasChildren()
|
|
106
|
+
or currentAttribute == RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE
|
|
107
|
+
or ONLY_USE_INSTANCES
|
|
108
|
+
|
|
109
|
+
-- Short circuit querying datamodel
|
|
110
|
+
local hasValidAttribute = currentAttribute ~= nil
|
|
111
|
+
and currentAttribute ~= RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE
|
|
112
|
+
if hasValidAttribute and not instanceRequired then
|
|
113
|
+
-- TODO: Interface/avoid attribute value/cache
|
|
114
|
+
return AttributeValue.new(parent, definition:GetName(), definition:GetEncodedDefaultValue())
|
|
115
|
+
end
|
|
116
|
+
|
|
81
117
|
local found
|
|
82
|
-
if self:CanInitialize() then
|
|
118
|
+
if self:CanInitialize() and instanceRequired then
|
|
83
119
|
found = definition:GetOrCreateInstance(parent)
|
|
84
120
|
else
|
|
85
121
|
found = parent:FindFirstChild(definition:GetName())
|
|
86
122
|
end
|
|
87
123
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
124
|
+
if found then
|
|
125
|
+
rawset(self, "_baseValueInstanceCache", found)
|
|
126
|
+
parent:SetAttribute(definition:GetName(), RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE)
|
|
127
|
+
return found
|
|
128
|
+
elseif not instanceRequired then
|
|
129
|
+
if self:CanInitialize() then
|
|
130
|
+
return AttributeValue.new(parent, definition:GetName(), definition:GetEncodedDefaultValue())
|
|
131
|
+
else
|
|
132
|
+
if currentAttribute ~= nil then
|
|
133
|
+
return AttributeValue.new(parent, definition:GetName(), definition:GetEncodedDefaultValue())
|
|
134
|
+
else
|
|
135
|
+
return nil
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
else
|
|
139
|
+
return nil
|
|
140
|
+
end
|
|
92
141
|
end
|
|
93
142
|
|
|
94
|
-
function RogueProperty:
|
|
143
|
+
function RogueProperty:_observeParentBrio()
|
|
144
|
+
local cache = rawget(self, "_observeParentBrioCache")
|
|
145
|
+
if cache then
|
|
146
|
+
return cache
|
|
147
|
+
end
|
|
148
|
+
|
|
95
149
|
local parentDefinition = self._definition:GetParentPropertyDefinition()
|
|
96
150
|
if parentDefinition then
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return RxInstanceUtils.observeLastNamedChildBrio(
|
|
100
|
-
container,
|
|
101
|
-
self._definition:GetStorageInstanceType(),
|
|
102
|
-
self._definition:GetName()
|
|
103
|
-
)
|
|
104
|
-
end),
|
|
105
|
-
})
|
|
151
|
+
local parentTable = parentDefinition:Get(self._serviceBag, self._adornee)
|
|
152
|
+
cache = parentTable:ObserveContainerBrio()
|
|
106
153
|
else
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
self._definition:GetStorageInstanceType(),
|
|
110
|
-
self._definition:GetName()
|
|
111
|
-
)
|
|
154
|
+
-- TODO: Performance very sad, unneeded table construction
|
|
155
|
+
cache = RxBrioUtils.of(self._adornee)
|
|
112
156
|
end
|
|
157
|
+
|
|
158
|
+
rawset(self, "_observeParentBrioCache", cache)
|
|
159
|
+
|
|
160
|
+
return cache
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
function RogueProperty:_observeBaseValueBrio()
|
|
164
|
+
local cache = rawget(self, "_observeBaseValueBrioCache")
|
|
165
|
+
if cache then
|
|
166
|
+
return cache
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
cache = self:_observeParentBrio():Pipe({
|
|
170
|
+
RxBrioUtils.switchMapBrio(function(container)
|
|
171
|
+
return RxInstanceUtils.observeLastNamedChildBrio(
|
|
172
|
+
container,
|
|
173
|
+
self._definition:GetStorageInstanceType(),
|
|
174
|
+
self._definition:GetName()
|
|
175
|
+
)
|
|
176
|
+
end),
|
|
177
|
+
Rx.cache(),
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
rawset(self, "_observeBaseValueBrioCache", cache)
|
|
181
|
+
|
|
182
|
+
return cache
|
|
113
183
|
end
|
|
114
184
|
|
|
115
185
|
function RogueProperty:SetBaseValue(value)
|
|
116
186
|
assert(self._definition:CanAssign(value, false)) -- This has a good error message
|
|
117
187
|
|
|
118
|
-
local baseValue = self:GetBaseValueObject()
|
|
188
|
+
local baseValue = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
119
189
|
if baseValue then
|
|
120
190
|
baseValue.Value = self:_encodeValue(value)
|
|
121
191
|
else
|
|
@@ -129,18 +199,130 @@ function RogueProperty:SetBaseValue(value)
|
|
|
129
199
|
end
|
|
130
200
|
end
|
|
131
201
|
|
|
202
|
+
function RogueProperty:_getModifierParentContainerForNewModifier()
|
|
203
|
+
if self:CanInitialize() then
|
|
204
|
+
return self:GetBaseValueObject(RoguePropertyBaseValueTypes.INSTANCE)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
local found = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
208
|
+
if found then
|
|
209
|
+
if typeof(found) == "Instance" then
|
|
210
|
+
return found
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
-- else, search for local parent
|
|
215
|
+
local parent = self:_getParentContainer()
|
|
216
|
+
if not parent then
|
|
217
|
+
return nil
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
-- TODO: Maybe we should use this before anything else on the client...?
|
|
221
|
+
-- TODO: Maybe only do this on the client?
|
|
222
|
+
local name = self:_getLocalModifierParentName()
|
|
223
|
+
|
|
224
|
+
found = parent:FindFirstChild(name)
|
|
225
|
+
if found then
|
|
226
|
+
return found
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
local localParent = Instance.new(LOCAL_MODIFIER_CONTAINER_CLASS_NAME)
|
|
230
|
+
localParent.Name = name
|
|
231
|
+
localParent.Archivable = false
|
|
232
|
+
localParent.Parent = parent
|
|
233
|
+
|
|
234
|
+
return localParent
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
function RogueProperty:_getLocalModifierParentName()
|
|
238
|
+
return self._definition:GetName() .. "_LocalModifiers"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
function RogueProperty:_getModifierParentContainerList()
|
|
242
|
+
local containerList = {}
|
|
243
|
+
|
|
244
|
+
if self:CanInitialize() then
|
|
245
|
+
local found = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
246
|
+
if typeof(found) == "Instance" then
|
|
247
|
+
table.insert(containerList, found)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
local parent = self:_getParentContainer()
|
|
252
|
+
if parent then
|
|
253
|
+
local name = self:_getLocalModifierParentName()
|
|
254
|
+
|
|
255
|
+
local localParent = parent:FindFirstChild(name)
|
|
256
|
+
if localParent then
|
|
257
|
+
table.insert(containerList, localParent)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
return containerList
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
function RogueProperty:PromiseBaseValue()
|
|
265
|
+
return Rx.toPromise(self:_observeBaseValueBrio():Pipe({
|
|
266
|
+
RxBrioUtils.flattenToValueAndNil,
|
|
267
|
+
Rx.where(function(value)
|
|
268
|
+
return value ~= nil
|
|
269
|
+
end),
|
|
270
|
+
}))
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
function RogueProperty:_observeModifierContainersBrio()
|
|
274
|
+
local name = self:_getLocalModifierParentName()
|
|
275
|
+
|
|
276
|
+
return self:_observeParentBrio():Pipe({
|
|
277
|
+
RxBrioUtils.switchMapBrio(function(parent)
|
|
278
|
+
return Rx.merge({
|
|
279
|
+
-- The main container
|
|
280
|
+
RxAttributeUtils.observeAttributeBrio(parent, self._definition:GetName(), function(attribute)
|
|
281
|
+
return attribute == RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE
|
|
282
|
+
end):Pipe({
|
|
283
|
+
Rx.switchMap(function()
|
|
284
|
+
return self:_observeBaseValueBrio()
|
|
285
|
+
end),
|
|
286
|
+
}),
|
|
287
|
+
|
|
288
|
+
-- The modifier parent
|
|
289
|
+
RxInstanceUtils.observeChildrenBrio(parent, function(child)
|
|
290
|
+
return child:IsA(LOCAL_MODIFIER_CONTAINER_CLASS_NAME) and child.Name == name
|
|
291
|
+
end),
|
|
292
|
+
})
|
|
293
|
+
end),
|
|
294
|
+
})
|
|
295
|
+
end
|
|
296
|
+
|
|
132
297
|
function RogueProperty:SetValue(value)
|
|
133
298
|
assert(self._definition:CanAssign(value, false)) -- This has a good error message
|
|
134
299
|
|
|
135
|
-
local baseValue = self:GetBaseValueObject()
|
|
300
|
+
local baseValue = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
136
301
|
if not baseValue then
|
|
137
|
-
|
|
302
|
+
local warningText = debug.traceback(
|
|
138
303
|
string.format(
|
|
139
304
|
"[RogueProperty.SetValue] - Failed to get the baseValue for %q on %q",
|
|
140
305
|
self._definition:GetFullName(),
|
|
141
306
|
self._adornee:GetFullName()
|
|
142
307
|
)
|
|
143
308
|
)
|
|
309
|
+
|
|
310
|
+
local warnTask = task.delay(5, function()
|
|
311
|
+
warn(warningText)
|
|
312
|
+
end)
|
|
313
|
+
|
|
314
|
+
self:PromiseBaseValue():Then(function(thisBaseValue)
|
|
315
|
+
local current = value
|
|
316
|
+
|
|
317
|
+
local modifiers = self:GetRogueModifiers()
|
|
318
|
+
for i = #modifiers, 1, -1 do
|
|
319
|
+
current = modifiers[i]:GetInvertedVersion(current, value)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
thisBaseValue.Value = self:_encodeValue(current)
|
|
323
|
+
task.cancel(warnTask)
|
|
324
|
+
end)
|
|
325
|
+
|
|
144
326
|
return
|
|
145
327
|
end
|
|
146
328
|
|
|
@@ -155,7 +337,7 @@ function RogueProperty:SetValue(value)
|
|
|
155
337
|
end
|
|
156
338
|
|
|
157
339
|
function RogueProperty:GetBaseValue()
|
|
158
|
-
local baseValue = self:GetBaseValueObject()
|
|
340
|
+
local baseValue = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
159
341
|
if baseValue then
|
|
160
342
|
return self:_decodeValue(baseValue.Value)
|
|
161
343
|
else
|
|
@@ -164,7 +346,7 @@ function RogueProperty:GetBaseValue()
|
|
|
164
346
|
end
|
|
165
347
|
|
|
166
348
|
function RogueProperty:GetValue()
|
|
167
|
-
local propObj = self:GetBaseValueObject()
|
|
349
|
+
local propObj = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
168
350
|
if not propObj then
|
|
169
351
|
return self._definition:GetDefaultValue()
|
|
170
352
|
end
|
|
@@ -183,63 +365,99 @@ function RogueProperty:GetDefinition()
|
|
|
183
365
|
end
|
|
184
366
|
|
|
185
367
|
function RogueProperty:GetRogueModifiers()
|
|
186
|
-
local
|
|
187
|
-
|
|
188
|
-
|
|
368
|
+
local modifierList = {}
|
|
369
|
+
|
|
370
|
+
for _, parent in self:_getModifierParentContainerList() do
|
|
371
|
+
for _, modifier in RogueModifierInterface:GetChildren(parent, self._tieRealmService:GetTieRealm()) do
|
|
372
|
+
table.insert(modifierList, modifier)
|
|
373
|
+
end
|
|
189
374
|
end
|
|
190
375
|
|
|
191
|
-
|
|
376
|
+
if not next(modifierList) then
|
|
377
|
+
return modifierList
|
|
378
|
+
end
|
|
192
379
|
|
|
193
|
-
local
|
|
194
|
-
for _, item in
|
|
195
|
-
|
|
380
|
+
local orderMap = {}
|
|
381
|
+
for _, item in modifierList do
|
|
382
|
+
orderMap[item] = item.Order.Value
|
|
196
383
|
end
|
|
197
|
-
table.sort(
|
|
198
|
-
return
|
|
384
|
+
table.sort(modifierList, function(a, b)
|
|
385
|
+
return orderMap[a] < orderMap[b]
|
|
199
386
|
end)
|
|
200
387
|
|
|
201
|
-
return
|
|
388
|
+
return modifierList
|
|
202
389
|
end
|
|
203
390
|
|
|
204
391
|
function RogueProperty:_observeModifierSortedList()
|
|
205
|
-
|
|
392
|
+
local cache = rawget(self, "_observeModifierSortedListCache")
|
|
393
|
+
if cache then
|
|
394
|
+
return cache
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
cache = Observable.new(function(sub)
|
|
206
398
|
local topMaid = Maid.new()
|
|
207
399
|
|
|
208
400
|
local sortedList = topMaid:Add(ObservableSortedList.new())
|
|
209
401
|
|
|
210
|
-
topMaid:GiveTask(self:
|
|
402
|
+
topMaid:GiveTask(self:_observeModifierContainersBrio()
|
|
211
403
|
:Pipe({
|
|
212
404
|
RxBrioUtils.flatMapBrio(function(baseValue)
|
|
213
|
-
return RogueModifierInterface:ObserveChildrenBrio(baseValue)
|
|
405
|
+
return RogueModifierInterface:ObserveChildrenBrio(baseValue, self._tieRealmService:GetTieRealm())
|
|
214
406
|
end),
|
|
215
407
|
})
|
|
216
408
|
:Subscribe(function(brio)
|
|
217
409
|
if brio:IsDead() then
|
|
218
410
|
return
|
|
219
411
|
end
|
|
412
|
+
|
|
220
413
|
local maid, rogueModifier = brio:ToMaidAndValue()
|
|
221
414
|
maid:GiveTask(sortedList:Add(rogueModifier, rogueModifier.Order:Observe()))
|
|
222
415
|
end))
|
|
223
416
|
|
|
417
|
+
debug.profilebegin("sorted_list_add")
|
|
224
418
|
sub:Fire(sortedList)
|
|
419
|
+
debug.profileend()
|
|
225
420
|
|
|
226
421
|
return topMaid
|
|
227
422
|
end):Pipe({
|
|
228
423
|
Rx.cache(),
|
|
229
424
|
})
|
|
425
|
+
|
|
426
|
+
rawset(self, "_observeModifierSortedListCache", cache)
|
|
427
|
+
return cache
|
|
230
428
|
end
|
|
231
429
|
|
|
232
430
|
function RogueProperty:Observe()
|
|
233
|
-
local
|
|
234
|
-
|
|
235
|
-
|
|
431
|
+
local cache = rawget(self, "_observeCache")
|
|
432
|
+
if cache then
|
|
433
|
+
return cache
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
local observeInitialValue = self:_observeParentBrio():Pipe({
|
|
437
|
+
RxBrioUtils.switchMapBrio(function(parent)
|
|
438
|
+
return RxAttributeUtils.observeAttribute(parent, self._definition:GetName())
|
|
439
|
+
end),
|
|
440
|
+
RxBrioUtils.switchMapBrio(function(attribute)
|
|
441
|
+
if attribute == RoguePropertyConstants.INSTANCE_ATTRIBUTE_VALUE then
|
|
442
|
+
return self:_observeBaseValueBrio():Pipe({
|
|
443
|
+
RxBrioUtils.switchMapBrio(function(baseValue)
|
|
444
|
+
return RxInstanceUtils.observeProperty(baseValue, "Value")
|
|
445
|
+
end),
|
|
446
|
+
})
|
|
447
|
+
end
|
|
448
|
+
local decoded = self:_decodeValue(attribute)
|
|
449
|
+
if decoded == nil then
|
|
450
|
+
return Rx.of(self._definition:GetDefaultValue())
|
|
451
|
+
else
|
|
452
|
+
return Rx.of(decoded)
|
|
453
|
+
end
|
|
236
454
|
end),
|
|
237
455
|
RxBrioUtils.emitOnDeath(self._definition:GetDefaultValue()),
|
|
238
456
|
Rx.defaultsTo(self._definition:GetDefaultValue()),
|
|
239
457
|
Rx.distinct(),
|
|
240
458
|
})
|
|
241
459
|
|
|
242
|
-
|
|
460
|
+
cache = self:_observeModifierSortedList():Pipe({
|
|
243
461
|
Rx.switchMap(function(sortedList)
|
|
244
462
|
return sortedList:Observe()
|
|
245
463
|
end),
|
|
@@ -250,7 +468,10 @@ function RogueProperty:Observe()
|
|
|
250
468
|
end
|
|
251
469
|
return current
|
|
252
470
|
end),
|
|
471
|
+
Rx.cache(),
|
|
253
472
|
})
|
|
473
|
+
rawset(self, "_observeCache", cache)
|
|
474
|
+
return cache
|
|
254
475
|
end
|
|
255
476
|
|
|
256
477
|
function RogueProperty:ObserveBrio(predicate)
|
|
@@ -259,20 +480,9 @@ function RogueProperty:ObserveBrio(predicate)
|
|
|
259
480
|
})
|
|
260
481
|
end
|
|
261
482
|
|
|
262
|
-
function RogueProperty:CreateMultiplier(amount, source)
|
|
483
|
+
function RogueProperty:CreateMultiplier(amount: number, source)
|
|
263
484
|
assert(type(amount) == "number", "Bad amount")
|
|
264
485
|
|
|
265
|
-
local baseValue = self:GetBaseValueObject()
|
|
266
|
-
if not baseValue then
|
|
267
|
-
warn(
|
|
268
|
-
string.format(
|
|
269
|
-
"[RogueProperty.CreateMultiplier] - Failed to get the baseValue for %q on %q",
|
|
270
|
-
self._definition:GetFullName(),
|
|
271
|
-
self._adornee:GetFullName()
|
|
272
|
-
)
|
|
273
|
-
)
|
|
274
|
-
end
|
|
275
|
-
|
|
276
486
|
local className = ValueBaseUtils.getClassNameFromType(typeof(amount))
|
|
277
487
|
if not className then
|
|
278
488
|
error(string.format("[RogueProperty.CreateMultiplier] - Can't set to type %q", typeof(amount)))
|
|
@@ -289,7 +499,7 @@ function RogueProperty:CreateMultiplier(amount, source)
|
|
|
289
499
|
|
|
290
500
|
RogueMultiplier:Tag(multiplier)
|
|
291
501
|
|
|
292
|
-
multiplier
|
|
502
|
+
self:_parentModifier(multiplier)
|
|
293
503
|
|
|
294
504
|
return multiplier
|
|
295
505
|
end
|
|
@@ -297,18 +507,6 @@ end
|
|
|
297
507
|
function RogueProperty:CreateAdditive(amount: number, source)
|
|
298
508
|
assert(type(amount) == "number", "Bad amount")
|
|
299
509
|
|
|
300
|
-
local baseValue = self:GetBaseValueObject()
|
|
301
|
-
if not baseValue then
|
|
302
|
-
warn(
|
|
303
|
-
string.format(
|
|
304
|
-
"[RogueProperty.CreateAdditive] - Failed to get the baseValue for %q on %q",
|
|
305
|
-
self._definition:GetFullName(),
|
|
306
|
-
self._adornee:GetFullName()
|
|
307
|
-
)
|
|
308
|
-
)
|
|
309
|
-
return nil
|
|
310
|
-
end
|
|
311
|
-
|
|
312
510
|
local className = ValueBaseUtils.getClassNameFromType(typeof(amount))
|
|
313
511
|
if not className then
|
|
314
512
|
error(string.format("[RogueProperty.CreateAdditive] - Can't set to type %q", typeof(amount)))
|
|
@@ -325,19 +523,22 @@ function RogueProperty:CreateAdditive(amount: number, source)
|
|
|
325
523
|
|
|
326
524
|
RogueAdditive:Tag(additive)
|
|
327
525
|
|
|
328
|
-
additive
|
|
526
|
+
self:_parentModifier(additive)
|
|
329
527
|
|
|
330
528
|
return additive
|
|
331
529
|
end
|
|
332
530
|
|
|
333
531
|
function RogueProperty:GetNamedAdditive(name, source)
|
|
334
|
-
local
|
|
335
|
-
if not
|
|
532
|
+
local modifierParent = self:_getModifierParentContainerForNewModifier()
|
|
533
|
+
if not modifierParent then
|
|
534
|
+
-- TODO: Handle this parenting scenario appropriately
|
|
336
535
|
warn(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
536
|
+
debug.traceback(
|
|
537
|
+
string.format(
|
|
538
|
+
"[RogueProperty.GetNamedAdditive] - Failed to get the modifierParent for %q on %q",
|
|
539
|
+
self._definition:GetFullName(),
|
|
540
|
+
self._adornee:GetFullName()
|
|
541
|
+
)
|
|
341
542
|
)
|
|
342
543
|
)
|
|
343
544
|
return nil
|
|
@@ -345,7 +546,7 @@ function RogueProperty:GetNamedAdditive(name, source)
|
|
|
345
546
|
|
|
346
547
|
local searchName = name .. "Additive"
|
|
347
548
|
|
|
348
|
-
local found =
|
|
549
|
+
local found = modifierParent:FindFirstChild(searchName)
|
|
349
550
|
if found then
|
|
350
551
|
return found
|
|
351
552
|
end
|
|
@@ -356,18 +557,6 @@ function RogueProperty:GetNamedAdditive(name, source)
|
|
|
356
557
|
end
|
|
357
558
|
|
|
358
559
|
function RogueProperty:CreateSetter(value, source)
|
|
359
|
-
local baseValue = self:GetBaseValueObject()
|
|
360
|
-
if not baseValue then
|
|
361
|
-
warn(
|
|
362
|
-
string.format(
|
|
363
|
-
"[RogueProperty.CreateSetter] - Failed to get the baseValue for %q on %q",
|
|
364
|
-
self._definition:GetFullName(),
|
|
365
|
-
self._adornee:GetFullName()
|
|
366
|
-
)
|
|
367
|
-
)
|
|
368
|
-
return nil
|
|
369
|
-
end
|
|
370
|
-
|
|
371
560
|
local className = ValueBaseUtils.getClassNameFromType(typeof(value))
|
|
372
561
|
if not className then
|
|
373
562
|
error(string.format("[RogueProperty.CreateSetter] - Can't set to type %q", typeof(value)))
|
|
@@ -384,18 +573,61 @@ function RogueProperty:CreateSetter(value, source)
|
|
|
384
573
|
|
|
385
574
|
RogueSetter:Tag(setter)
|
|
386
575
|
|
|
387
|
-
setter
|
|
576
|
+
self:_parentModifier(setter)
|
|
388
577
|
|
|
389
578
|
return setter
|
|
390
579
|
end
|
|
391
580
|
|
|
581
|
+
function RogueProperty:_parentModifier(modifier: Instance)
|
|
582
|
+
local modifierParent = self:_getModifierParentContainerForNewModifier()
|
|
583
|
+
if modifierParent then
|
|
584
|
+
modifier.Parent = modifierParent
|
|
585
|
+
|
|
586
|
+
return
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
local maid = Maid.new()
|
|
590
|
+
|
|
591
|
+
local warningText = debug.traceback(
|
|
592
|
+
string.format(
|
|
593
|
+
"[RogueProperty._parentModifier] - Failed to get the modifierParent for %q on %q",
|
|
594
|
+
self._definition:GetFullName(),
|
|
595
|
+
self._adornee:GetFullName()
|
|
596
|
+
)
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
maid._warning = task.delay(5, function()
|
|
600
|
+
warn(warningText)
|
|
601
|
+
end)
|
|
602
|
+
|
|
603
|
+
maid:GivePromise(self:PromiseBaseValue()):Then(function()
|
|
604
|
+
local newParent = self:_getModifierParentContainerForNewModifier()
|
|
605
|
+
if not newParent then
|
|
606
|
+
warn(
|
|
607
|
+
"[RogueProperty:_parentModifier] - Failed to retrieve modifier parent after load, will never modify value"
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
return
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
maid._warning = nil
|
|
614
|
+
modifier.Parent = newParent
|
|
615
|
+
end)
|
|
616
|
+
|
|
617
|
+
maid:GiveTask(modifier.Destroying:Connect(function()
|
|
618
|
+
maid:DoCleaning()
|
|
619
|
+
end))
|
|
620
|
+
|
|
621
|
+
return
|
|
622
|
+
end
|
|
623
|
+
|
|
392
624
|
function RogueProperty:__index(index)
|
|
393
|
-
if index
|
|
625
|
+
if RogueProperty[index] then
|
|
626
|
+
return RogueProperty[index]
|
|
627
|
+
elseif index == "Value" then
|
|
394
628
|
return self:GetValue()
|
|
395
629
|
elseif index == "Changed" then
|
|
396
630
|
return self:GetChangedEvent()
|
|
397
|
-
elseif RogueProperty[index] then
|
|
398
|
-
return RogueProperty[index]
|
|
399
631
|
else
|
|
400
632
|
error(string.format("Bad index %q", tostring(index)))
|
|
401
633
|
end
|
|
@@ -6,6 +6,7 @@ local require = require(script.Parent.loader).load(script)
|
|
|
6
6
|
|
|
7
7
|
local BaseObject = require("BaseObject")
|
|
8
8
|
local RoguePropertyArrayUtils = require("RoguePropertyArrayUtils")
|
|
9
|
+
local RoguePropertyBaseValueTypes = require("RoguePropertyBaseValueTypes")
|
|
9
10
|
local Rx = require("Rx")
|
|
10
11
|
|
|
11
12
|
local RoguePropertyArrayHelper = setmetatable({}, BaseObject)
|
|
@@ -113,7 +114,11 @@ function RoguePropertyArrayHelper:SetArrayBaseData(arrayData)
|
|
|
113
114
|
else
|
|
114
115
|
-- Cleanup this old one and setup a new one
|
|
115
116
|
if available[index] then
|
|
116
|
-
available[index]:GetBaseValueObject()
|
|
117
|
+
local found = available[index]:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
118
|
+
if typeof(found) == "Instance" then
|
|
119
|
+
found:Destroy()
|
|
120
|
+
return
|
|
121
|
+
end
|
|
117
122
|
end
|
|
118
123
|
|
|
119
124
|
local property = definition:Get(self._serviceBag, adornee)
|
|
@@ -144,11 +149,18 @@ function RoguePropertyArrayHelper:SetArrayData(arrayData)
|
|
|
144
149
|
|
|
145
150
|
for index, definition in definitions do
|
|
146
151
|
if available[index] and available[index]:GetDefinition():GetValueType() == definition:GetValueType() then
|
|
152
|
+
-- TODO: Replication is cursed here, and won't be consistent between client vs. server
|
|
153
|
+
available[index]:SetCanInitialize(true)
|
|
147
154
|
available[index]:SetValue(definition:GetDefaultValue())
|
|
155
|
+
available[index]:SetCanInitialize(false)
|
|
148
156
|
else
|
|
149
157
|
-- Cleanup this old one and setup a new one
|
|
150
158
|
if available[index] then
|
|
151
|
-
available[index]:GetBaseValueObject()
|
|
159
|
+
local found = available[index]:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
|
|
160
|
+
if typeof(found) == "Instance" then
|
|
161
|
+
found:Destroy()
|
|
162
|
+
return
|
|
163
|
+
end
|
|
152
164
|
end
|
|
153
165
|
|
|
154
166
|
local property = definition:Get(self._serviceBag, adornee)
|
|
@@ -7,6 +7,8 @@ local require = require(script.Parent.loader).load(script)
|
|
|
7
7
|
local RogueProperty = require("RogueProperty")
|
|
8
8
|
local RoguePropertyArrayHelper = require("RoguePropertyArrayHelper")
|
|
9
9
|
local Rx = require("Rx")
|
|
10
|
+
local RxBrioUtils = require("RxBrioUtils")
|
|
11
|
+
local RxInstanceUtils = require("RxInstanceUtils")
|
|
10
12
|
local ServiceBag = require("ServiceBag")
|
|
11
13
|
|
|
12
14
|
local RoguePropertyTable = {} -- inherits from RogueProperty
|
|
@@ -29,29 +31,81 @@ end
|
|
|
29
31
|
function RoguePropertyTable:SetCanInitialize(canInitialize: boolean)
|
|
30
32
|
assert(type(canInitialize) == "boolean", "Bad canInitialize")
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
if self:CanInitialize() ~= canInitialize then
|
|
35
|
+
RogueProperty.SetCanInitialize(self, canInitialize)
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
for _, property in self:GetRogueProperties() do
|
|
38
|
+
property:SetCanInitialize(canInitialize)
|
|
39
|
+
end
|
|
37
40
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
local arrayHelper = rawget(self, "_arrayHelper")
|
|
42
|
+
if arrayHelper then
|
|
43
|
+
arrayHelper:SetCanInitialize(canInitialize)
|
|
44
|
+
end
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
function RoguePropertyTable:ObserveContainerBrio()
|
|
45
|
-
|
|
49
|
+
local cache = rawget(self, "_observeContainerCache")
|
|
50
|
+
if cache then
|
|
51
|
+
return cache
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
local parentDefinition = self._definition:GetParentPropertyDefinition()
|
|
55
|
+
if parentDefinition then
|
|
56
|
+
local parentTable = parentDefinition:Get(self._serviceBag, self._adornee)
|
|
57
|
+
|
|
58
|
+
if self:CanInitialize() then
|
|
59
|
+
parentTable:GetContainer()
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
cache = parentTable:ObserveContainerBrio():Pipe({
|
|
63
|
+
RxBrioUtils.switchMapBrio(function(parent)
|
|
64
|
+
return RxInstanceUtils.observeLastNamedChildBrio(parent, "Folder", self._definition:GetName())
|
|
65
|
+
end),
|
|
66
|
+
Rx.cache(),
|
|
67
|
+
})
|
|
68
|
+
else
|
|
69
|
+
cache = RxInstanceUtils.observeLastNamedChildBrio(self._adornee, "Folder", self._definition:GetName()):Pipe({
|
|
70
|
+
Rx.cache(),
|
|
71
|
+
})
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
cache = cache
|
|
75
|
+
rawset(self, "_observeContainerCache", cache)
|
|
76
|
+
return cache
|
|
46
77
|
end
|
|
47
78
|
|
|
48
|
-
function RoguePropertyTable:GetContainer(): Instance
|
|
79
|
+
function RoguePropertyTable:GetContainer(): Instance?
|
|
49
80
|
local cached = rawget(self, "_containerCache")
|
|
50
|
-
if cached
|
|
51
|
-
|
|
81
|
+
if cached then
|
|
82
|
+
if cached:IsDescendantOf(self._adornee) then
|
|
83
|
+
return cached
|
|
84
|
+
else
|
|
85
|
+
rawset(self, "_containerCache", nil)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
local parent
|
|
90
|
+
local parentDefinition = self._definition:GetParentPropertyDefinition()
|
|
91
|
+
if parentDefinition then
|
|
92
|
+
local parentTable = parentDefinition:Get(self._serviceBag, self._adornee)
|
|
93
|
+
parent = parentTable:GetContainer()
|
|
94
|
+
else
|
|
95
|
+
parent = self._adornee
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if not parent then
|
|
99
|
+
return nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
local container
|
|
103
|
+
if self:CanInitialize() then
|
|
104
|
+
container = self._definition:GetOrCreateInstance(parent)
|
|
105
|
+
else
|
|
106
|
+
container = self._definition:FindInstance(parent)
|
|
52
107
|
end
|
|
53
108
|
|
|
54
|
-
local container = self._definition:GetContainer(self._adornee, self:CanInitialize())
|
|
55
109
|
rawset(self, "_containerCache", container)
|
|
56
110
|
return container
|
|
57
111
|
end
|
|
@@ -167,6 +221,10 @@ end
|
|
|
167
221
|
|
|
168
222
|
function RoguePropertyTable:_observeDictionary()
|
|
169
223
|
-- ok, this is definitely slow
|
|
224
|
+
local cache = rawget(self, "_observeDictionaryCache")
|
|
225
|
+
if cache then
|
|
226
|
+
return cache
|
|
227
|
+
end
|
|
170
228
|
|
|
171
229
|
local toObserve = {}
|
|
172
230
|
|
|
@@ -180,10 +238,16 @@ function RoguePropertyTable:_observeDictionary()
|
|
|
180
238
|
end
|
|
181
239
|
|
|
182
240
|
if next(toObserve) == nil then
|
|
183
|
-
|
|
241
|
+
cache = Rx.of({})
|
|
242
|
+
else
|
|
243
|
+
cache = Rx.combineLatest(toObserve):Pipe({
|
|
244
|
+
Rx.cache(),
|
|
245
|
+
})
|
|
184
246
|
end
|
|
185
247
|
|
|
186
|
-
|
|
248
|
+
rawset(self, "_observeDictionaryCache", cache)
|
|
249
|
+
|
|
250
|
+
return cache
|
|
187
251
|
end
|
|
188
252
|
|
|
189
253
|
function RoguePropertyTable:GetRogueProperty(name: string)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class RoguePropertyBaseValueTypeUtils
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local RoguePropertyBaseValueTypes = require("RoguePropertyBaseValueTypes")
|
|
8
|
+
|
|
9
|
+
local RoguePropertyBaseValueTypeUtils = {}
|
|
10
|
+
|
|
11
|
+
function RoguePropertyBaseValueTypeUtils.isRoguePropertyBaseValueType(value)
|
|
12
|
+
return value == RoguePropertyBaseValueTypes.INSTANCE or value == RoguePropertyBaseValueTypes.ANY
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
return RoguePropertyBaseValueTypeUtils
|