@quenty/soundgroup 1.26.0-canary.00067520041c.0 → 1.26.1-canary.bf9591f.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,46 @@
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
- # [1.26.0-canary.00067520041c.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.25.5...@quenty/soundgroup@1.26.0-canary.00067520041c.0) (2025-12-29)
6
+ ## [1.26.1-canary.bf9591f.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.26.0...@quenty/soundgroup@1.26.1-canary.bf9591f.0) (2026-01-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Update the sound group package to include sound volume multipliers ([bf9591f](https://github.com/Quenty/NevermoreEngine/commit/bf9591fe2d08dbefae47f8c449b7bbf20c01fdfe))
12
+
13
+
14
+
15
+
16
+
17
+ # [1.26.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.25.8...@quenty/soundgroup@1.26.0) (2026-01-04)
18
+
19
+ **Note:** Version bump only for package @quenty/soundgroup
20
+
21
+
22
+
23
+
24
+
25
+ ## [1.25.8](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.25.7...@quenty/soundgroup@1.25.8) (2026-01-03)
26
+
27
+ **Note:** Version bump only for package @quenty/soundgroup
28
+
29
+
30
+
31
+
32
+
33
+ ## [1.25.7](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.25.6...@quenty/soundgroup@1.25.7) (2025-12-31)
34
+
35
+
36
+ ### Bug Fixes
37
+
38
+ * Fix dependencies missing in packages ([97bd47d](https://github.com/Quenty/NevermoreEngine/commit/97bd47d341017152f91a28d8444252d20a8de9fa))
39
+ * Fix directory declaration in soundgroups ([862839d](https://github.com/Quenty/NevermoreEngine/commit/862839d5fb9026a74e81123c813081c5c6496789))
40
+
41
+
42
+
43
+
44
+
45
+ ## [1.25.6](https://github.com/Quenty/NevermoreEngine/compare/@quenty/soundgroup@1.25.5...@quenty/soundgroup@1.25.6) (2025-12-29)
7
46
 
8
47
  **Note:** Version bump only for package @quenty/soundgroup
9
48
 
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2014-2025 James Onnen (Quenty)
3
+ Copyright (c) 2014-2026 James Onnen (Quenty)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/soundgroup",
3
- "version": "1.26.0-canary.00067520041c.0",
3
+ "version": "1.26.1-canary.bf9591f.0",
4
4
  "description": "Service and utility methods to working with sound groups and sounds in Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -14,7 +14,7 @@
14
14
  "repository": {
15
15
  "type": "git",
16
16
  "url": "https://github.com/Quenty/NevermoreEngine.git",
17
- "directory": "src/soundgroup/"
17
+ "directory": "src/soundgroups/"
18
18
  },
19
19
  "funding": {
20
20
  "type": "patreon",
@@ -25,20 +25,25 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/baseobject": "10.9.0",
29
- "@quenty/brio": "14.21.0-canary.00067520041c.0",
30
- "@quenty/counter": "7.22.0-canary.00067520041c.0",
31
- "@quenty/instanceutils": "13.21.0-canary.00067520041c.0",
32
- "@quenty/loader": "10.9.0",
33
- "@quenty/maid": "3.5.0",
34
- "@quenty/observablecollection": "12.25.0-canary.00067520041c.0",
35
- "@quenty/rx": "13.21.0-canary.00067520041c.0",
36
- "@quenty/signal": "7.12.0-canary.00067520041c.0",
37
- "@quenty/table": "3.8.0",
38
- "@quenty/valueobject": "13.22.0-canary.00067520041c.0"
28
+ "@quenty/baseobject": "10.9.1",
29
+ "@quenty/binder": "14.26.1-canary.bf9591f.0",
30
+ "@quenty/brio": "14.21.0",
31
+ "@quenty/counter": "7.22.1-canary.bf9591f.0",
32
+ "@quenty/instanceutils": "13.21.0",
33
+ "@quenty/loader": "10.9.1",
34
+ "@quenty/maid": "3.5.1",
35
+ "@quenty/observablecollection": "12.25.1-canary.bf9591f.0",
36
+ "@quenty/promise": "10.12.4",
37
+ "@quenty/rogue-properties": "11.31.1-canary.bf9591f.0",
38
+ "@quenty/rx": "13.21.0",
39
+ "@quenty/servicebag": "11.13.4",
40
+ "@quenty/signal": "7.11.3",
41
+ "@quenty/table": "3.9.0",
42
+ "@quenty/tie": "10.27.1-canary.bf9591f.0",
43
+ "@quenty/valueobject": "13.22.1-canary.bf9591f.0"
39
44
  },
40
45
  "publishConfig": {
41
46
  "access": "public"
42
47
  },
43
- "gitHead": "00067520041c809a1cf0d94230a08118a8f62212"
48
+ "gitHead": "bf9591fe2d08dbefae47f8c449b7bbf20c01fdfe"
44
49
  }
@@ -1,3 +1,4 @@
1
+ --!nonstrict
1
2
  --[=[
2
3
  @class SoundGroupServiceClient
3
4
  ]=]
@@ -15,6 +16,10 @@ function SoundGroupServiceClient:Init(serviceBag: ServiceBag.ServiceBag)
15
16
  self._serviceBag = assert(serviceBag, "No serviceBag")
16
17
  self._maid = Maid.new()
17
18
 
19
+ -- External
20
+ self._serviceBag:GetService(require("TieRealmService"))
21
+ self._serviceBag:GetService(require("RoguePropertyService"))
22
+
18
23
  -- Internal
19
24
  self._serviceBag:GetService(require("SoundEffectService"))
20
25
  end
@@ -1,3 +1,4 @@
1
+ --!nonstrict
1
2
  --[=[
2
3
  @class SoundGroupService
3
4
  ]=]
@@ -16,6 +17,10 @@ function SoundGroupService:Init(serviceBag: ServiceBag.ServiceBag)
16
17
  self._serviceBag = assert(serviceBag, "No serviceBag")
17
18
  self._maid = Maid.new()
18
19
 
20
+ -- External
21
+ self._serviceBag:GetService(require("TieRealmService"))
22
+ self._serviceBag:GetService(require("RoguePropertyService"))
23
+
19
24
  -- Internal
20
25
  self._soundEffectService = self._serviceBag:GetService(require("SoundEffectService"))
21
26
  end
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Handles applying global volume and effects to specific sounds in a group based upon a path.
3
4
 
@@ -10,25 +11,46 @@ local RunService = game:GetService("RunService")
10
11
  local SoundService = game:GetService("SoundService")
11
12
 
12
13
  local Maid = require("Maid")
14
+ local Promise = require("Promise")
13
15
  local ServiceBag = require("ServiceBag")
16
+ local SoundEffectsList = require("SoundEffectsList")
14
17
  local SoundEffectsRegistry = require("SoundEffectsRegistry")
15
18
  local SoundGroupPathUtils = require("SoundGroupPathUtils")
16
19
  local SoundGroupTracker = require("SoundGroupTracker")
20
+ local SoundGroupVolume = require("SoundGroupVolume")
17
21
  local WellKnownSoundGroups = require("WellKnownSoundGroups")
18
22
 
19
23
  local SoundEffectService = {}
20
24
  SoundEffectService.ServiceName = "SoundEffectService"
21
25
 
22
- function SoundEffectService:Init(serviceBag: ServiceBag.ServiceBag)
23
- assert(not self._serviceBag, "Already initialized")
26
+ export type SoundEffectService = typeof(setmetatable(
27
+ {} :: {
28
+ _serviceBag: ServiceBag.ServiceBag,
29
+ _maid: Maid.Maid,
30
+ _soundEffectsRegister: any, -- SoundEffectsRegistry.SoundEffectsRegistry,
31
+ _tracker: any, -- SoundGroupTracker.SoundGroupTracker,
32
+ },
33
+ {} :: typeof({ __index = SoundEffectService })
34
+ ))
35
+
36
+ function SoundEffectService.Init(self: SoundEffectService, serviceBag: ServiceBag.ServiceBag)
37
+ assert(not (self :: any)._serviceBag, "Already initialized")
24
38
  self._serviceBag = assert(serviceBag, "No serviceBag")
25
39
  self._maid = Maid.new()
26
40
 
41
+ -- External
42
+ self._serviceBag:GetService(require("TieRealmService"))
43
+ self._serviceBag:GetService(require("RoguePropertyService"))
44
+
45
+ -- State
27
46
  self._soundEffectsRegister = self._maid:Add(SoundEffectsRegistry.new())
28
47
  self._tracker = self._maid:Add(SoundGroupTracker.new(SoundService))
48
+
49
+ -- Binders
50
+ self._serviceBag:GetService(require("SoundGroupVolume"))
29
51
  end
30
52
 
31
- function SoundEffectService:Start()
53
+ function SoundEffectService.Start(self: SoundEffectService): ()
32
54
  self:_setupEffectApplication()
33
55
  end
34
56
 
@@ -37,14 +59,42 @@ end
37
59
  @param sound Sound
38
60
  @param soundGroupPath string? -- Optional
39
61
  ]=]
40
- function SoundEffectService:RegisterSFX(sound: Sound, soundGroupPath: string?)
62
+ function SoundEffectService.RegisterSFX(self: SoundEffectService, sound: Sound, soundGroupPath: string): ()
41
63
  assert(typeof(sound) == "Instance" and sound:IsA("Sound"), "Bad sound")
42
64
  assert(SoundGroupPathUtils.isSoundGroupPath(soundGroupPath) or soundGroupPath == nil, "Bad soundGroupPath")
43
65
 
44
66
  sound.SoundGroup = self:GetOrCreateSoundGroup(soundGroupPath or WellKnownSoundGroups.SFX)
45
67
  end
46
68
 
47
- function SoundEffectService:GetOrCreateSoundGroup(soundGroupPath: string): SoundGroup
69
+ --[=[
70
+ Creates a NumberValue multiplier for the given sound group path.
71
+
72
+ Destroy (or unparent) the returned NumberValue to remove the multiplier.
73
+
74
+ @param soundGroupPath string
75
+ @return Promise<NumberValue>
76
+ ]=]
77
+ function SoundEffectService:PromiseCreateVolumeMultiplier(soundGroupPath: string): Promise.Promise<NumberValue>
78
+ local soundGroup = self:GetOrCreateSoundGroup(soundGroupPath)
79
+ if soundGroup == nil then
80
+ return Promise.rejected("Failed to get or create sound group for path: " .. soundGroupPath)
81
+ end
82
+
83
+ local soundGroupVolumeBinder = self._serviceBag:GetService(require("SoundGroupVolume"))
84
+ soundGroupVolumeBinder:Tag(soundGroup)
85
+
86
+ return soundGroupVolumeBinder:Promise(soundGroup):Then(function(soundGroupVolume)
87
+ return soundGroupVolume:CreateMultiplier()
88
+ end)
89
+ end
90
+
91
+ --[=[
92
+ Returns the SoundGroup for the given path, creating it if it does not exist.
93
+
94
+ @param soundGroupPath string
95
+ @return SoundGroup
96
+ ]=]
97
+ function SoundEffectService.GetOrCreateSoundGroup(self: SoundEffectService, soundGroupPath: string): SoundGroup
48
98
  assert(SoundGroupPathUtils.isSoundGroupPath(soundGroupPath), "Bad soundGroupPath")
49
99
 
50
100
  local found = self:GetSoundGroup(soundGroupPath)
@@ -53,10 +103,21 @@ function SoundEffectService:GetOrCreateSoundGroup(soundGroupPath: string): Sound
53
103
  end
54
104
 
55
105
  -- Handle deferred mode
56
- return SoundGroupPathUtils.findOrCreateSoundGroup(soundGroupPath)
106
+ found = SoundGroupPathUtils.findOrCreateSoundGroup(soundGroupPath)
107
+ assert(found, "Failed to create sound group for path")
108
+
109
+ SoundGroupVolume:Tag(found)
110
+
111
+ return found
57
112
  end
58
113
 
59
- function SoundEffectService:GetSoundGroup(soundGroupPath: string): SoundGroup
114
+ --[=[
115
+ Returns the SoundGroup for the given path, or nil if it does not exist.
116
+
117
+ @param soundGroupPath string
118
+ @return SoundGroup
119
+ ]=]
120
+ function SoundEffectService.GetSoundGroup(self: SoundEffectService, soundGroupPath: string): SoundGroup?
60
121
  assert(SoundGroupPathUtils.isSoundGroupPath(soundGroupPath), "Bad soundGroupPath")
61
122
 
62
123
  if not self._tracker then
@@ -70,27 +131,41 @@ function SoundEffectService:GetSoundGroup(soundGroupPath: string): SoundGroup
70
131
 
71
132
  local found = self._tracker:GetFirstSoundGroup(soundGroupPath)
72
133
  if found then
134
+ SoundGroupVolume:Tag(found)
73
135
  return found
74
136
  end
75
137
 
76
- return SoundGroupPathUtils.findOrCreateSoundGroup(soundGroupPath)
138
+ found = SoundGroupPathUtils.findSoundGroup(soundGroupPath)
139
+ if found then
140
+ SoundGroupVolume:Tag(found)
141
+ end
142
+
143
+ return found
77
144
  end
78
145
 
79
- function SoundEffectService:PushEffect(soundGroupPath: string, effect)
146
+ function SoundEffectService.PushEffect(
147
+ self: SoundEffectService,
148
+ soundGroupPath: string,
149
+ effect: SoundEffectsList.SoundEffectApplier
150
+ ): ()
80
151
  assert(SoundGroupPathUtils.isSoundGroupPath(soundGroupPath), "Bad soundGroupPath")
81
152
  assert(type(effect) == "function", "Bad effect")
82
153
 
83
154
  return self._soundEffectsRegister:PushEffect(soundGroupPath, effect)
84
155
  end
85
156
 
86
- function SoundEffectService:ApplyEffects(soundGroupPath, instance)
157
+ function SoundEffectService.ApplyEffects(
158
+ self: SoundEffectService,
159
+ soundGroupPath: string,
160
+ instance: SoundGroup | Sound
161
+ ): () -> ()
87
162
  assert(SoundGroupPathUtils.isSoundGroupPath(soundGroupPath), "Bad soundGroupPath")
88
163
  assert(typeof(instance) == "Instance" and (instance:IsA("SoundGroup") or instance:IsA("Sound")), "Bad instance")
89
164
 
90
165
  return self._soundEffectsRegister:ApplyEffects(soundGroupPath, instance)
91
166
  end
92
167
 
93
- function SoundEffectService:_setupEffectApplication()
168
+ function SoundEffectService._setupEffectApplication(self: SoundEffectService): ()
94
169
  self._maid:GiveTask(self._tracker:ObserveSoundGroupsBrio():Subscribe(function(brio)
95
170
  if brio:IsDead() then
96
171
  return
@@ -101,7 +176,7 @@ function SoundEffectService:_setupEffectApplication()
101
176
  if soundGroupPath then
102
177
  maid._currentEffects = self._soundEffectsRegister:ApplyEffects(soundGroupPath, soundGroup)
103
178
  else
104
- maid._currentEffects = nil
179
+ maid._currentEffects = nil :: any
105
180
  end
106
181
  end))
107
182
  end))
@@ -121,7 +196,7 @@ function SoundEffectService:_setupEffectApplication()
121
196
  end))
122
197
  end
123
198
 
124
- function SoundEffectService:Destroy()
199
+ function SoundEffectService.Destroy(self: SoundEffectService): ()
125
200
  self._maid:DoCleaning()
126
201
  end
127
202
 
@@ -0,0 +1,65 @@
1
+ --!strict
2
+ local SoundGroupVolumeInterface = require(script.Parent.SoundGroupVolumeInterface)
3
+ --[=[
4
+ @class SoundGroupVolume
5
+ ]=]
6
+
7
+ local require = require(script.Parent.loader).load(script)
8
+
9
+ local BaseObject = require("BaseObject")
10
+ local Binder = require("Binder")
11
+ local ServiceBag = require("ServiceBag")
12
+ local SoundGroupVolumeProperties = require("SoundGroupVolumeProperties")
13
+ local TieRealms = require("TieRealms")
14
+
15
+ local SoundGroupVolume = setmetatable({}, BaseObject)
16
+ SoundGroupVolume.ClassName = "SoundGroupVolume"
17
+ SoundGroupVolume.__index = SoundGroupVolume
18
+
19
+ export type SoundGroupVolume =
20
+ typeof(setmetatable(
21
+ {} :: {
22
+ _obj: SoundGroup,
23
+ _serviceBag: ServiceBag.ServiceBag,
24
+ _tieRealmService: any,
25
+ _properties: any,
26
+ RenderedVolume: any,
27
+ },
28
+ {} :: typeof({ __index = SoundGroupVolume })
29
+ ))
30
+ & BaseObject.BaseObject
31
+
32
+ function SoundGroupVolume.new(instance: SoundGroup, serviceBag: ServiceBag.ServiceBag): SoundGroupVolume
33
+ local self: SoundGroupVolume = setmetatable(BaseObject.new(instance) :: any, SoundGroupVolume)
34
+
35
+ self._serviceBag = assert(serviceBag, "No serviceBag")
36
+ self._tieRealmService = self._serviceBag:GetService(require("TieRealmService"))
37
+
38
+ self._properties = SoundGroupVolumeProperties:Get(self._serviceBag, self._obj)
39
+ self.RenderedVolume = self._properties.Volume
40
+
41
+ self._maid:GiveTask(SoundGroupVolumeInterface:Implement(self._obj, self, self._tieRealmService:GetTieRealm()))
42
+
43
+ -- Assign our volume to the current volume if we're on the server
44
+ if self._tieRealmService:GetTieRealm() == TieRealms.SERVER then
45
+ self._properties.Volume:SetBaseValue(self._obj.Volume)
46
+ end
47
+
48
+ self._maid:GiveTask(self._properties.Volume:Observe():Subscribe(function(volume)
49
+ self._obj.Volume = volume
50
+ end))
51
+
52
+ return self
53
+ end
54
+
55
+ --[=[
56
+ Creates a volume multiplier for this sound group volume.
57
+
58
+ @param amount number?
59
+ @return NumberValue
60
+ ]=]
61
+ function SoundGroupVolume.CreateMultiplier(self: SoundGroupVolume, amount: number?): NumberValue
62
+ return self._properties.Volume:CreateMultiplier(amount or 1)
63
+ end
64
+
65
+ return Binder.new("SoundGroupVolume", SoundGroupVolume :: any) :: Binder.Binder<SoundGroupVolume>
@@ -0,0 +1,12 @@
1
+ --!strict
2
+ --[=[
3
+ @class SoundGroupVolumeInterface
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local TieDefinition = require("TieDefinition")
9
+
10
+ return TieDefinition.new("SoundGroupVolume", {
11
+ CreateMultiplier = TieDefinition.Types.METHOD,
12
+ })
@@ -0,0 +1,12 @@
1
+ --!strict
2
+ --[=[
3
+ @class SoundGroupVolumeProperties
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local RoguePropertyTableDefinition = require("RoguePropertyTableDefinition")
9
+
10
+ return RoguePropertyTableDefinition.new("SoundGroupVolume", {
11
+ Volume = 1,
12
+ })
@@ -1,3 +1,4 @@
1
+ --!nonstrict
1
2
  --[[
2
3
  @class ClientMain
3
4
  ]]
@@ -1,3 +1,4 @@
1
+ --!nonstrict
1
2
  --[[
2
3
  @class ServerMain
3
4
  ]]