@quenty/rogue-properties 11.25.2-canary.ff3c47a.0 → 11.26.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,12 +3,14 @@
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.ff3c47a.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rogue-properties@11.25.1...@quenty/rogue-properties@11.25.2-canary.ff3c47a.0) (2025-09-26)
6
+ # [11.26.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/rogue-properties@11.25.1...@quenty/rogue-properties@11.26.0) (2025-09-26)
7
7
 
8
8
 
9
9
  ### Bug Fixes
10
10
 
11
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))
12
14
  * Style stuff ([ff3c47a](https://github.com/Quenty/NevermoreEngine/commit/ff3c47af4e5b23f912aa09a0784849751d5736e1))
13
15
 
14
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/rogue-properties",
3
- "version": "11.25.2-canary.ff3c47a.0",
3
+ "version": "11.26.0",
4
4
  "description": "Roguelike properties which can be modified by external provides",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -24,35 +24,35 @@
24
24
  "Quenty"
25
25
  ],
26
26
  "dependencies": {
27
- "@quenty/adorneedata": "7.20.1-canary.ff3c47a.0",
28
- "@quenty/attributeutils": "14.19.1-canary.ff3c47a.0",
29
- "@quenty/baseobject": "10.9.0",
30
- "@quenty/binder": "14.22.1-canary.ff3c47a.0",
31
- "@quenty/brio": "14.19.1-canary.ff3c47a.0",
32
- "@quenty/defaultvalueutils": "1.2.2",
33
- "@quenty/ducktype": "5.9.0",
34
- "@quenty/instanceutils": "13.19.1-canary.ff3c47a.0",
35
- "@quenty/jsonutils": "10.12.0",
36
- "@quenty/linkutils": "13.19.1-canary.ff3c47a.0",
37
- "@quenty/loader": "10.9.0",
38
- "@quenty/maid": "3.5.0",
39
- "@quenty/observablecollection": "12.22.2-canary.ff3c47a.0",
40
- "@quenty/remoting": "12.20.1-canary.ff3c47a.0",
41
- "@quenty/rx": "13.19.1-canary.ff3c47a.0",
42
- "@quenty/rxbinderutils": "14.22.1-canary.ff3c47a.0",
43
- "@quenty/rxsignal": "7.19.1-canary.ff3c47a.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.ff3c47a.0",
50
- "@quenty/valuebaseutils": "13.19.1-canary.ff3c47a.0",
51
- "@quenty/valueobject": "13.19.1-canary.ff3c47a.0",
27
+ "@quenty/adorneedata": "^7.21.0",
28
+ "@quenty/attributeutils": "^14.20.0",
29
+ "@quenty/baseobject": "^10.9.0",
30
+ "@quenty/binder": "^14.23.0",
31
+ "@quenty/brio": "^14.20.0",
32
+ "@quenty/defaultvalueutils": "^1.2.2",
33
+ "@quenty/ducktype": "^5.9.0",
34
+ "@quenty/instanceutils": "^13.20.0",
35
+ "@quenty/jsonutils": "^10.12.0",
36
+ "@quenty/linkutils": "^13.20.0",
37
+ "@quenty/loader": "^10.9.0",
38
+ "@quenty/maid": "^3.5.0",
39
+ "@quenty/observablecollection": "^12.23.0",
40
+ "@quenty/remoting": "^12.21.0",
41
+ "@quenty/rx": "^13.20.0",
42
+ "@quenty/rxbinderutils": "^14.23.0",
43
+ "@quenty/rxsignal": "^7.20.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.23.0",
50
+ "@quenty/valuebaseutils": "^13.20.0",
51
+ "@quenty/valueobject": "^13.20.0",
52
52
  "@quentystudios/t": "^3.0.0"
53
53
  },
54
54
  "publishConfig": {
55
55
  "access": "public"
56
56
  },
57
- "gitHead": "ff3c47af4e5b23f912aa09a0784849751d5736e1"
57
+ "gitHead": "0ecdc6807f4ad638ffd49b056bceec4353895b82"
58
58
  }
@@ -232,41 +232,37 @@ RoguePropertyTableDefinition.GetPropertyTable = RoguePropertyTableDefinition.Get
232
232
 
233
233
  @return Observable<Brio<Folder>>
234
234
  ]=]
235
- function RoguePropertyTableDefinition:ObserveContainerBrio(
236
- serviceBag: ServiceBag.ServiceBag,
237
- adornee: Instance,
238
- canInitialize: boolean
239
- )
235
+ function RoguePropertyTableDefinition:ObserveContainerBrio(serviceBag: ServiceBag.ServiceBag, adornee: Instance)
236
+ assert(serviceBag, "No serviceBag")
240
237
  assert(typeof(adornee) == "Instance", "Bad adornee")
241
- assert(type(canInitialize) == "boolean", "Bad canInitialize")
242
238
 
243
239
  local found = self:Get(serviceBag, adornee)
244
240
 
245
241
  -- TODO: caninitialize is broken
246
242
 
247
- return found:ObserveContainerBrio(canInitialize)
243
+ return found:ObserveContainerBrio()
248
244
  end
249
245
 
250
246
  --[=[
251
247
  Gets the current container for the given adornee.
252
- @param adornee Instance
253
- @param canInitialize boolean
254
248
  @return Folder?
255
249
  ]=]
256
- function RoguePropertyTableDefinition:GetContainer(
257
- serviceBag: ServiceBag.ServiceBag,
258
- adornee: Instance,
259
- canInitialize: boolean
260
- ): Folder?
250
+ function RoguePropertyTableDefinition:GetContainer(serviceBag: ServiceBag.ServiceBag, adornee: Instance): Folder?
251
+ assert(serviceBag, "No serviceBag")
261
252
  assert(typeof(adornee) == "Instance", "Bad adornee")
262
- assert(type(canInitialize) == "boolean", "Bad canInitialize")
263
253
 
264
254
  local found = self:Get(serviceBag, adornee)
265
255
 
266
256
  return found:GetContainer()
267
257
  end
268
258
 
269
- function RoguePropertyTableDefinition:GetOrCreateInstance(parent)
259
+ function RoguePropertyTableDefinition:FindInstance(parent): Instance?
260
+ assert(typeof(parent) == "Instance", "Bad parent")
261
+
262
+ return parent:FindFirstChild(self:GetName())
263
+ end
264
+
265
+ function RoguePropertyTableDefinition:GetOrCreateInstance(parent): Folder
270
266
  assert(typeof(parent) == "Instance", "Bad parent")
271
267
 
272
268
  local existing = parent:FindFirstChild(self:GetName())
@@ -261,6 +261,15 @@ function RogueProperty:_getModifierParentContainerList()
261
261
  return containerList
262
262
  end
263
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
+
264
273
  function RogueProperty:_observeModifierContainersBrio()
265
274
  local name = self:_getLocalModifierParentName()
266
275
 
@@ -290,13 +299,30 @@ function RogueProperty:SetValue(value)
290
299
 
291
300
  local baseValue = self:GetBaseValueObject(RoguePropertyBaseValueTypes.ANY)
292
301
  if not baseValue then
293
- warn(
302
+ local warningText = debug.traceback(
294
303
  string.format(
295
304
  "[RogueProperty.SetValue] - Failed to get the baseValue for %q on %q",
296
305
  self._definition:GetFullName(),
297
306
  self._adornee:GetFullName()
298
307
  )
299
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
+
300
326
  return
301
327
  end
302
328
 
@@ -457,17 +483,6 @@ end
457
483
  function RogueProperty:CreateMultiplier(amount: number, source)
458
484
  assert(type(amount) == "number", "Bad amount")
459
485
 
460
- local modifierParent = self:_getModifierParentContainerForNewModifier()
461
- if not modifierParent then
462
- warn(
463
- string.format(
464
- "[RogueProperty.CreateMultiplier] - Failed to get the modifierParent for %q on %q",
465
- self._definition:GetFullName(),
466
- self._adornee:GetFullName()
467
- )
468
- )
469
- end
470
-
471
486
  local className = ValueBaseUtils.getClassNameFromType(typeof(amount))
472
487
  if not className then
473
488
  error(string.format("[RogueProperty.CreateMultiplier] - Can't set to type %q", typeof(amount)))
@@ -484,7 +499,7 @@ function RogueProperty:CreateMultiplier(amount: number, source)
484
499
 
485
500
  RogueMultiplier:Tag(multiplier)
486
501
 
487
- multiplier.Parent = modifierParent
502
+ self:_parentModifier(multiplier)
488
503
 
489
504
  return multiplier
490
505
  end
@@ -492,18 +507,6 @@ end
492
507
  function RogueProperty:CreateAdditive(amount: number, source)
493
508
  assert(type(amount) == "number", "Bad amount")
494
509
 
495
- local modifierParent = self:_getModifierParentContainerForNewModifier()
496
- if not modifierParent then
497
- warn(
498
- string.format(
499
- "[RogueProperty.CreateAdditive] - Failed to get the modifierParent for %q on %q",
500
- self._definition:GetFullName(),
501
- self._adornee:GetFullName()
502
- )
503
- )
504
- return nil
505
- end
506
-
507
510
  local className = ValueBaseUtils.getClassNameFromType(typeof(amount))
508
511
  if not className then
509
512
  error(string.format("[RogueProperty.CreateAdditive] - Can't set to type %q", typeof(amount)))
@@ -520,7 +523,7 @@ function RogueProperty:CreateAdditive(amount: number, source)
520
523
 
521
524
  RogueAdditive:Tag(additive)
522
525
 
523
- additive.Parent = modifierParent
526
+ self:_parentModifier(additive)
524
527
 
525
528
  return additive
526
529
  end
@@ -528,11 +531,14 @@ end
528
531
  function RogueProperty:GetNamedAdditive(name, source)
529
532
  local modifierParent = self:_getModifierParentContainerForNewModifier()
530
533
  if not modifierParent then
534
+ -- TODO: Handle this parenting scenario appropriately
531
535
  warn(
532
- string.format(
533
- "[RogueProperty.GetNamedAdditive] - Failed to get the modifierParent for %q on %q",
534
- self._definition:GetFullName(),
535
- self._adornee:GetFullName()
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
+ )
536
542
  )
537
543
  )
538
544
  return nil
@@ -551,18 +557,6 @@ function RogueProperty:GetNamedAdditive(name, source)
551
557
  end
552
558
 
553
559
  function RogueProperty:CreateSetter(value, source)
554
- local modifierParent = self:_getModifierParentContainerForNewModifier()
555
- if not modifierParent then
556
- warn(
557
- string.format(
558
- "[RogueProperty.CreateSetter] - Failed to get the modifierParent for %q on %q",
559
- self._definition:GetFullName(),
560
- self._adornee:GetFullName()
561
- )
562
- )
563
- return nil
564
- end
565
-
566
560
  local className = ValueBaseUtils.getClassNameFromType(typeof(value))
567
561
  if not className then
568
562
  error(string.format("[RogueProperty.CreateSetter] - Can't set to type %q", typeof(value)))
@@ -579,11 +573,54 @@ function RogueProperty:CreateSetter(value, source)
579
573
 
580
574
  RogueSetter:Tag(setter)
581
575
 
582
- setter.Parent = modifierParent
576
+ self:_parentModifier(setter)
583
577
 
584
578
  return setter
585
579
  end
586
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
+
587
624
  function RogueProperty:__index(index)
588
625
  if RogueProperty[index] then
589
626
  return RogueProperty[index]
@@ -149,7 +149,10 @@ function RoguePropertyArrayHelper:SetArrayData(arrayData)
149
149
 
150
150
  for index, definition in definitions do
151
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)
152
154
  available[index]:SetValue(definition:GetDefaultValue())
155
+ available[index]:SetCanInitialize(false)
153
156
  else
154
157
  -- Cleanup this old one and setup a new one
155
158
  if available[index] then
@@ -54,7 +54,10 @@ function RoguePropertyTable:ObserveContainerBrio()
54
54
  local parentDefinition = self._definition:GetParentPropertyDefinition()
55
55
  if parentDefinition then
56
56
  local parentTable = parentDefinition:Get(self._serviceBag, self._adornee)
57
- parentTable:GetContainer()
57
+
58
+ if self:CanInitialize() then
59
+ parentTable:GetContainer()
60
+ end
58
61
 
59
62
  cache = parentTable:ObserveContainerBrio():Pipe({
60
63
  RxBrioUtils.switchMapBrio(function(parent)
@@ -73,7 +76,7 @@ function RoguePropertyTable:ObserveContainerBrio()
73
76
  return cache
74
77
  end
75
78
 
76
- function RoguePropertyTable:GetContainer(): Instance
79
+ function RoguePropertyTable:GetContainer(): Instance?
77
80
  local cached = rawget(self, "_containerCache")
78
81
  if cached then
79
82
  if cached:IsDescendantOf(self._adornee) then
@@ -92,8 +95,16 @@ function RoguePropertyTable:GetContainer(): Instance
92
95
  parent = self._adornee
93
96
  end
94
97
 
95
- local container = self._definition:GetOrCreateInstance(parent, self:CanInitialize())
96
- container:AddTag("RoguePropertyTable")
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)
107
+ end
97
108
 
98
109
  rawset(self, "_containerCache", container)
99
110
  return container