@quenty/settings 2.3.1 → 3.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,6 +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
+ # [3.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/settings@2.3.1...@quenty/settings@3.0.0) (2022-08-14)
7
+
8
+ **Note:** Version bump only for package @quenty/settings
9
+
10
+
11
+
12
+
13
+
6
14
  ## [2.3.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/settings@2.3.0...@quenty/settings@2.3.1) (2022-08-11)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/settings",
3
- "version": "2.3.1",
3
+ "version": "3.0.0",
4
4
  "description": "Centralized player settings service",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,30 +25,31 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/attributeutils": "^6.2.0",
28
+ "@quenty/attributeutils": "^7.0.0",
29
29
  "@quenty/baseobject": "^5.1.0",
30
- "@quenty/binder": "^6.3.0",
31
- "@quenty/datastore": "^5.3.0",
30
+ "@quenty/binder": "^7.0.0",
31
+ "@quenty/datastore": "^6.0.0",
32
+ "@quenty/enumutils": "^2.0.0",
32
33
  "@quenty/jsonutils": "^5.1.0",
33
34
  "@quenty/loader": "^5.0.0",
34
35
  "@quenty/maid": "^2.4.0",
35
- "@quenty/observablecollection": "^3.3.1",
36
- "@quenty/playerbinder": "^6.3.0",
36
+ "@quenty/observablecollection": "^4.0.0",
37
+ "@quenty/playerbinder": "^7.0.0",
37
38
  "@quenty/remotefunctionutils": "^5.1.0",
38
39
  "@quenty/remoting": "^5.2.0",
39
- "@quenty/rx": "^5.2.0",
40
- "@quenty/rxbinderutils": "^6.3.0",
40
+ "@quenty/rx": "^6.0.0",
41
+ "@quenty/rxbinderutils": "^7.0.0",
41
42
  "@quenty/servicebag": "^5.1.0",
42
43
  "@quenty/signal": "^2.2.0",
43
- "@quenty/statestack": "^6.2.0",
44
- "@quenty/string": "^2.3.0",
44
+ "@quenty/statestack": "^7.0.0",
45
+ "@quenty/string": "^3.0.0",
45
46
  "@quenty/symbol": "^2.1.0",
46
47
  "@quenty/table": "^3.1.0",
47
48
  "@quenty/throttle": "^5.0.0",
48
- "@quenty/valueobject": "^5.2.0"
49
+ "@quenty/valueobject": "^6.0.0"
49
50
  },
50
51
  "publishConfig": {
51
52
  "access": "public"
52
53
  },
53
- "gitHead": "45ffe88b893e29690163a42c3830c983f6098a59"
54
+ "gitHead": "dbb62609f980983cc32da90acfef13e30ed41113"
54
55
  }
@@ -16,7 +16,7 @@ function SettingsServiceClient:Init(serviceBag)
16
16
  self._serviceBag = assert(serviceBag, "No serviceBag")
17
17
 
18
18
  -- Internal
19
- self._serviceBag:GetService(require("SettingServiceBridge")):RegisterSettingService(self)
19
+ self._serviceBag:GetService(require("SettingRegistryServiceShared")):RegisterSettingService(self)
20
20
  self._binders = self._serviceBag:GetService(require("SettingsBindersClient"))
21
21
  end
22
22
 
@@ -40,7 +40,7 @@ function PlayerHasSettings:_promiseLoadSettings()
40
40
  :Then(function(settings)
41
41
  for settingName, value in pairs(settings) do
42
42
  local attributeName = PlayerSettingsUtils.getAttributeName(settingName)
43
- self._settings:SetAttribute(attributeName, value)
43
+ self._settings:SetAttribute(attributeName, PlayerSettingsUtils.encodeForAttribute(value))
44
44
  end
45
45
 
46
46
  self._maid:GiveTask(self._settings.AttributeChanged:Connect(function(attributeName)
@@ -64,7 +64,7 @@ function PlayerHasSettings:_handleAttributeChanged(subStore, attributeName)
64
64
 
65
65
  -- Write the new value
66
66
  local settingName = PlayerSettingsUtils.getSettingName(attributeName)
67
- local newValue = self._settings:GetAttribute(attributeName)
67
+ local newValue = PlayerSettingsUtils.decodeForAttribute(self._settings:GetAttribute(attributeName))
68
68
  subStore:Store(settingName, newValue)
69
69
  end
70
70
 
@@ -7,7 +7,7 @@ local require = require(script.Parent.loader).load(script)
7
7
  local PlayerSettingsBase = require("PlayerSettingsBase")
8
8
  local PlayerSettingsConstants = require("PlayerSettingsConstants")
9
9
  local PlayerSettingsUtils = require("PlayerSettingsUtils")
10
- local SettingServiceBridge = require("SettingServiceBridge")
10
+ local SettingRegistryServiceShared = require("SettingRegistryServiceShared")
11
11
 
12
12
  local PlayerSettings = setmetatable({}, PlayerSettingsBase)
13
13
  PlayerSettings.ClassName = "PlayerSettings"
@@ -16,7 +16,8 @@ PlayerSettings.__index = PlayerSettings
16
16
  function PlayerSettings.new(obj, serviceBag)
17
17
  local self = setmetatable(PlayerSettingsBase.new(obj, serviceBag), PlayerSettings)
18
18
 
19
- self._bridge = self._serviceBag:GetService(SettingServiceBridge)
19
+ self._serviceBag = assert(serviceBag, "No serviceBag")
20
+ self._settingRegistryServiceShared = self._serviceBag:GetService(SettingRegistryServiceShared)
20
21
 
21
22
  self._remoteFunction = Instance.new("RemoteFunction")
22
23
  self._remoteFunction.Name = PlayerSettingsConstants.REMOTE_FUNCTION_NAME
@@ -28,7 +29,7 @@ function PlayerSettings.new(obj, serviceBag)
28
29
  return self:_handleServerInvoke(...)
29
30
  end
30
31
 
31
- self._maid:GiveTask(self._bridge:ObserveRegisteredDefinitionsBrio():Subscribe(function(brio)
32
+ self._maid:GiveTask(self._settingRegistryServiceShared:ObserveRegisteredDefinitionsBrio():Subscribe(function(brio)
32
33
  if brio:IsDead() then
33
34
  return
34
35
  end
@@ -46,7 +47,7 @@ function PlayerSettings:EnsureInitialized(settingName, defaultValue)
46
47
  local attributeName = PlayerSettingsUtils.getAttributeName(settingName)
47
48
 
48
49
  if self._obj:GetAttribute(attributeName) == nil then
49
- self._obj:SetAttribute(attributeName, defaultValue)
50
+ self._obj:SetAttribute(attributeName, PlayerSettingsUtils.encodeForAttribute(defaultValue))
50
51
  end
51
52
  end
52
53
 
@@ -69,12 +70,12 @@ function PlayerSettings:_setSettings(settingsMap)
69
70
  local attributeName = PlayerSettingsUtils.getAttributeName(settingName)
70
71
 
71
72
  if self._obj:GetAttribute(attributeName) == nil then
72
- warn("[PlayerSettings] - Cannot set setting on attribute that is not defined on the server")
73
+ warn(("[PlayerSettings] - Cannot set setting %q on attribute that is not defined on the server."):format(attributeName))
73
74
  continue
74
75
  end
75
76
 
76
77
  local decoded = PlayerSettingsUtils.decodeForNetwork(value)
77
- self._obj:SetAttribute(attributeName, decoded)
78
+ self._obj:SetAttribute(attributeName, PlayerSettingsUtils.encodeForAttribute(decoded))
78
79
  end
79
80
  end
80
81
 
@@ -18,7 +18,7 @@ function SettingsService:Init(serviceBag)
18
18
 
19
19
  -- Internal
20
20
  self._binders = self._serviceBag:GetService(require("SettingsBindersServer"))
21
- self._serviceBag:GetService(require("SettingServiceBridge")):RegisterSettingService(self)
21
+ self._serviceBag:GetService(require("SettingRegistryServiceShared")):RegisterSettingService(self)
22
22
  end
23
23
 
24
24
  function SettingsService:ObservePlayerSettingsBrio(player)
@@ -8,6 +8,7 @@ local BaseObject = require("BaseObject")
8
8
  local PlayerSettingsUtils = require("PlayerSettingsUtils")
9
9
  local RxAttributeUtils = require("RxAttributeUtils")
10
10
  local SettingDefinition = require("SettingDefinition")
11
+ local Rx = require("Rx")
11
12
 
12
13
  local PlayerSettingsBase = setmetatable({}, BaseObject)
13
14
  PlayerSettingsBase.ClassName = "PlayerSettingsBase"
@@ -45,13 +46,13 @@ end
45
46
  @param defaultValue any
46
47
  @return SettingProperty
47
48
  ]=]
48
- function PlayerSettingsBase:GetSetting(settingName, defaultValue)
49
+ function PlayerSettingsBase:GetSettingProperty(settingName, defaultValue)
49
50
  assert(type(settingName) == "string", "Bad settingName")
50
51
  assert(defaultValue ~= nil, "defaultValue cannot be nil")
51
52
 
52
53
  self:EnsureInitialized(settingName, defaultValue)
53
54
 
54
- return SettingDefinition.new(settingName, defaultValue):Get(self._serviceBag, self:GetPlayer())
55
+ return SettingDefinition.new(settingName, defaultValue):GetSettingProperty(self._serviceBag, self:GetPlayer())
55
56
  end
56
57
 
57
58
  --[=[
@@ -69,7 +70,7 @@ function PlayerSettingsBase:GetValue(settingName, defaultValue)
69
70
 
70
71
  self:EnsureInitialized(settingName, defaultValue)
71
72
 
72
- local value = self._obj:GetAttribute(attributeName)
73
+ local value = PlayerSettingsUtils.decodeForAttribute(self._obj:GetAttribute(attributeName))
73
74
  if value == nil then
74
75
  return defaultValue
75
76
  end
@@ -89,7 +90,7 @@ function PlayerSettingsBase:SetValue(settingName, value)
89
90
 
90
91
  local attributeName = PlayerSettingsUtils.getAttributeName(settingName)
91
92
 
92
- self._obj:SetAttribute(attributeName, value)
93
+ self._obj:SetAttribute(attributeName, PlayerSettingsUtils.encodeForAttribute(value))
93
94
  end
94
95
 
95
96
  --[=[
@@ -108,6 +109,9 @@ function PlayerSettingsBase:ObserveValue(settingName, defaultValue)
108
109
  self:EnsureInitialized(settingName, defaultValue)
109
110
 
110
111
  return RxAttributeUtils.observeAttribute(self._obj, attributeName, defaultValue)
112
+ :Pipe({
113
+ Rx.map(PlayerSettingsUtils.decodeForAttribute)
114
+ })
111
115
  end
112
116
 
113
117
  function PlayerSettingsBase:RestoreDefault(settingName, defaultValue)
@@ -10,6 +10,7 @@ local RxBinderUtils = require("RxBinderUtils")
10
10
  local BinderUtils = require("BinderUtils")
11
11
  local Binder = require("Binder")
12
12
  local RxStateStackUtils = require("RxStateStackUtils")
13
+ local EnumUtils = require("EnumUtils")
13
14
 
14
15
  local PlayerSettingsUtils = {}
15
16
 
@@ -68,6 +69,8 @@ function PlayerSettingsUtils.encodeForNetwork(settingValue)
68
69
 
69
70
  if settingValue == nil then
70
71
  return "<NIL_SETTING_VALUE>"
72
+ elseif typeof(settingValue) == "EnumItem" then
73
+ return EnumUtils.encodeAsString(settingValue)
71
74
  else
72
75
  return settingValue
73
76
  end
@@ -76,6 +79,24 @@ end
76
79
  function PlayerSettingsUtils.decodeForNetwork(settingValue)
77
80
  if settingValue == "<NIL_SETTING_VALUE>" then
78
81
  return nil
82
+ elseif EnumUtils.isEncodedEnum(settingValue) then
83
+ return EnumUtils.decodeFromString(settingValue)
84
+ else
85
+ return settingValue
86
+ end
87
+ end
88
+
89
+ function PlayerSettingsUtils.decodeForAttribute(settingValue)
90
+ if EnumUtils.isEncodedEnum(settingValue) then
91
+ return EnumUtils.decodeFromString(settingValue)
92
+ else
93
+ return settingValue
94
+ end
95
+ end
96
+
97
+ function PlayerSettingsUtils.encodeForAttribute(settingValue)
98
+ if typeof(settingValue) == "EnumItem" then
99
+ return EnumUtils.encodeAsString(settingValue)
79
100
  else
80
101
  return settingValue
81
102
  end
@@ -7,11 +7,11 @@ local require = require(script.Parent.loader).load(script)
7
7
  local Players = game:GetService("Players")
8
8
 
9
9
  local SettingProperty = require("SettingProperty")
10
- local SettingServiceBridge = require("SettingServiceBridge")
11
10
  local ServiceBag = require("ServiceBag")
12
11
 
13
12
  local SettingDefinition = {}
14
13
  SettingDefinition.ClassName = "SettingDefinition"
14
+ SettingDefinition.ServiceName = "SettingDefinition"
15
15
  SettingDefinition.__index = SettingDefinition
16
16
 
17
17
  --[=[
@@ -30,6 +30,8 @@ function SettingDefinition.new(settingName, defaultValue)
30
30
  self._settingName = settingName
31
31
  self._defaultValue = defaultValue
32
32
 
33
+ self.ServiceName = self._settingName
34
+
33
35
  return self
34
36
  end
35
37
 
@@ -75,36 +77,4 @@ function SettingDefinition:GetDefaultValue()
75
77
  return self._defaultValue
76
78
  end
77
79
 
78
- --[=[
79
- Optional registration to the service bag. If registered, ensures all existing
80
- players and all new players get this setting defined. This may be necessary for
81
- replication.
82
-
83
- @param serviceBag ServiceBag
84
- ]=]
85
- function SettingDefinition:Init(serviceBag)
86
- assert(ServiceBag.isServiceBag(serviceBag), "Bad serviceBag")
87
- -- not strictly necessary... but...
88
-
89
- serviceBag:GetService(SettingServiceBridge):RegisterDefinition(self)
90
- end
91
-
92
- --[=[
93
- Optional registration to the service bag
94
-
95
- @param serviceBag ServiceBag
96
- ]=]
97
- function SettingDefinition:RegisterToService(serviceBag)
98
- assert(ServiceBag.isServiceBag(serviceBag), "Bad serviceBag")
99
-
100
- local settingServiceBridge = serviceBag:GetService(SettingServiceBridge)
101
-
102
- if serviceBag:IsStarted() and not serviceBag:HasService(self) then
103
- -- We've already started so let's ensure
104
- settingServiceBridge:RegisterDefinition(self)
105
- else
106
- settingServiceBridge:RegisterDefinition(serviceBag:GetService(self))
107
- end
108
- end
109
-
110
80
  return SettingDefinition
@@ -4,10 +4,12 @@
4
4
 
5
5
  local require = require(script.Parent.loader).load(script)
6
6
 
7
- local SettingServiceBridge = require("SettingServiceBridge")
7
+ local SettingRegistryServiceShared = require("SettingRegistryServiceShared")
8
+ local Maid = require("Maid")
8
9
 
9
10
  local SettingDefinitionProvider = {}
10
11
  SettingDefinitionProvider.ClassName = "SettingDefinitionProvider"
12
+ SettingDefinitionProvider.ServiceName = "SettingDefinitionProvider"
11
13
  SettingDefinitionProvider.__index = SettingDefinitionProvider
12
14
 
13
15
  function SettingDefinitionProvider.new(settingDefinitions)
@@ -26,11 +28,13 @@ end
26
28
 
27
29
  function SettingDefinitionProvider:Init(serviceBag)
28
30
  assert(serviceBag, "No serviceBag")
31
+ assert(not self._maid, "Already initialized")
29
32
 
30
- serviceBag:GetService(SettingServiceBridge)
33
+ self._maid = Maid.new()
31
34
 
35
+ local settingRegistryServiceShared = serviceBag:GetService(SettingRegistryServiceShared)
32
36
  for _, settingDefinition in pairs(self._settingDefinitions) do
33
- settingDefinition:RegisterToService(serviceBag)
37
+ self._maid:GiveTask(settingRegistryServiceShared:RegisterSettingDefinition(settingDefinition))
34
38
  end
35
39
  end
36
40
 
@@ -45,7 +49,7 @@ end
45
49
  function SettingDefinitionProvider:__index(index)
46
50
  if SettingDefinitionProvider[index] then
47
51
  return SettingDefinitionProvider[index]
48
- elseif index == "_lookup" or index == "_settingDefinitions" then
52
+ elseif index == "_lookup" or index == "_settingDefinitions" or index == "_maid" then
49
53
  return rawget(self, index)
50
54
  elseif type(index) == "string" then
51
55
  local lookup = rawget(self, "_lookup")
@@ -64,4 +68,8 @@ function SettingDefinitionProvider:Get(settingName)
64
68
  return self._lookup[settingName]
65
69
  end
66
70
 
71
+ function SettingDefinitionProvider:Destroy()
72
+ self._maid:DoCleaning()
73
+ end
74
+
67
75
  return SettingDefinitionProvider
@@ -4,7 +4,7 @@
4
4
 
5
5
  local require = require(script.Parent.loader).load(script)
6
6
 
7
- local SettingServiceBridge = require("SettingServiceBridge")
7
+ local SettingRegistryServiceShared = require("SettingRegistryServiceShared")
8
8
  local Rx = require("Rx")
9
9
 
10
10
  local SettingProperty = {}
@@ -15,7 +15,7 @@ function SettingProperty.new(serviceBag, player, definition)
15
15
  local self = setmetatable({}, SettingProperty)
16
16
 
17
17
  self._serviceBag = assert(serviceBag, "No serviceBag")
18
- self._bridge = self._serviceBag:GetService(SettingServiceBridge)
18
+ self._bridge = self._serviceBag:GetService(SettingRegistryServiceShared)
19
19
 
20
20
  self._player = assert(player, "No player")
21
21
  self._definition = assert(definition, "No definition")
@@ -1,5 +1,7 @@
1
1
  --[=[
2
- @class SettingServiceBridge
2
+ Shared between client and server, letting us centralize definitions in one place.
3
+
4
+ @class SettingRegistryServiceShared
3
5
  ]=]
4
6
 
5
7
  local require = require(script.Parent.loader).load(script)
@@ -8,9 +10,9 @@ local ValueObject = require("ValueObject")
8
10
  local Rx = require("Rx")
9
11
  local ObservableSet = require("ObservableSet")
10
12
 
11
- local SettingServiceBridge = {}
13
+ local SettingRegistryServiceShared = {}
12
14
 
13
- function SettingServiceBridge:Init(serviceBag)
15
+ function SettingRegistryServiceShared:Init(serviceBag)
14
16
  assert(not self._serviceBag, "Already initialized")
15
17
  self._serviceBag = assert(serviceBag, "No serviceBag")
16
18
 
@@ -18,29 +20,29 @@ function SettingServiceBridge:Init(serviceBag)
18
20
  self._settingDefinitions = ObservableSet.new()
19
21
  end
20
22
 
21
- function SettingServiceBridge:RegisterSettingService(settingService)
23
+ function SettingRegistryServiceShared:RegisterSettingService(settingService)
22
24
  self._settingService.Value = settingService
23
25
  end
24
26
 
25
- function SettingServiceBridge:RegisterDefinition(definition)
27
+ function SettingRegistryServiceShared:RegisterSettingDefinition(definition)
26
28
  assert(definition, "No definition")
27
29
 
28
30
  return self._settingDefinitions:Add(definition)
29
31
  end
30
32
 
31
- function SettingServiceBridge:ObserveRegisteredDefinitionsBrio()
33
+ function SettingRegistryServiceShared:ObserveRegisteredDefinitionsBrio()
32
34
  return self._settingDefinitions:ObserveItemsBrio()
33
35
  end
34
36
 
35
- function SettingServiceBridge:GetSettingsService()
37
+ function SettingRegistryServiceShared:GetSettingsService()
36
38
  return self._settingService.Value
37
39
  end
38
40
 
39
- function SettingServiceBridge:ObserveSettingsService()
41
+ function SettingRegistryServiceShared:ObserveSettingsService()
40
42
  return self._settingService:Observe()
41
43
  end
42
44
 
43
- function SettingServiceBridge:ObservePlayerSettings(player)
45
+ function SettingRegistryServiceShared:ObservePlayerSettings(player)
44
46
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
45
47
 
46
48
  return self:ObserveSettingsService():Pipe({
@@ -54,7 +56,7 @@ function SettingServiceBridge:ObservePlayerSettings(player)
54
56
  })
55
57
  end
56
58
 
57
- function SettingServiceBridge:PromisePlayerSettings(player)
59
+ function SettingRegistryServiceShared:PromisePlayerSettings(player)
58
60
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
59
61
 
60
62
  return Rx.toPromise(self._settingService:Observe():Pipe({
@@ -67,7 +69,7 @@ function SettingServiceBridge:PromisePlayerSettings(player)
67
69
  end)
68
70
  end
69
71
 
70
- function SettingServiceBridge:GetPlayerSettings(player)
72
+ function SettingRegistryServiceShared:GetPlayerSettings(player)
71
73
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
72
74
 
73
75
  local settingService = self._settingService.Value
@@ -78,4 +80,4 @@ function SettingServiceBridge:GetPlayerSettings(player)
78
80
  end
79
81
  end
80
82
 
81
- return SettingServiceBridge
83
+ return SettingRegistryServiceShared
@@ -8,6 +8,7 @@ local packages = require(loader).bootstrapGame(ServerScriptService.settings)
8
8
 
9
9
  local serviceBag = require(packages.ServiceBag).new()
10
10
  serviceBag:GetService(packages.SettingsService)
11
+ local bridge = serviceBag:GetService(packages.SettingsServiceBridge)
11
12
 
12
13
  local SettingDefinition = require(packages.SettingDefinition)
13
14
 
@@ -20,10 +21,10 @@ serviceBag:Start()
20
21
 
21
22
 
22
23
  local volumeDefinition = SettingDefinition.new("Volume", 1)
23
- volumeDefinition:RegisterToService(serviceBag)
24
+ bridge:RegisterSettingDefinition(volumeDefinition)
24
25
 
25
26
  local rumbleDefinition = SettingDefinition.new("Rumble", true)
26
- rumbleDefinition:RegisterToService(serviceBag)
27
+ bridge:RegisterSettingDefinition(rumbleDefinition)
27
28
 
28
29
 
29
30
  local function handlePlayer(player)