@quenty/gameproductservice 14.34.8-canary.ba2274e.0 → 14.34.8
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 +1 -1
- package/package.json +30 -30
- package/src/Client/GameProductServiceClient.lua +1 -0
- package/src/Client/Manager/PlayerProductManagerClient.lua +44 -19
- package/src/Server/Cmdr/GameProductCmdrService.lua +1 -0
- package/src/Server/GameProductService.lua +1 -0
- package/src/Server/Manager/PlayerProductManager.lua +21 -9
- package/src/Shared/Interfaces/PlayerAssetMarketTrackerInterface.lua +1 -0
- package/src/Shared/Interfaces/PlayerProductManagerInterface.lua +1 -0
- package/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua +31 -8
- package/src/Shared/Trackers/PlayerAssetMarketTracker.lua +70 -19
- package/src/Shared/Trackers/PlayerProductManagerBase.lua +61 -24
- package/test/scripts/Client/ClientMain.client.lua +1 -0
- package/test/scripts/Server/ServerMain.server.lua +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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
|
-
## [14.34.8
|
|
6
|
+
## [14.34.8](https://github.com/Quenty/NevermoreEngine/compare/@quenty/gameproductservice@14.34.7...@quenty/gameproductservice@14.34.8) (2026-01-03)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @quenty/gameproductservice
|
|
9
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/gameproductservice",
|
|
3
|
-
"version": "14.34.8
|
|
3
|
+
"version": "14.34.8",
|
|
4
4
|
"description": "Generalized monetization system for handling products and purchases correctly.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -27,34 +27,34 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@quenty/attributeutils": "14.20.
|
|
31
|
-
"@quenty/avatareditorutils": "7.25.
|
|
32
|
-
"@quenty/baseobject": "10.9.
|
|
33
|
-
"@quenty/binder": "14.25.7
|
|
34
|
-
"@quenty/brio": "14.20.
|
|
35
|
-
"@quenty/cmdrservice": "13.29.
|
|
36
|
-
"@quenty/enumutils": "3.4.
|
|
37
|
-
"@quenty/gameconfig": "12.33.8
|
|
38
|
-
"@quenty/instanceutils": "13.20.
|
|
39
|
-
"@quenty/loader": "10.9.
|
|
40
|
-
"@quenty/maid": "3.5.
|
|
41
|
-
"@quenty/marketplaceutils": "11.13.
|
|
42
|
-
"@quenty/observablecollection": "12.24.
|
|
43
|
-
"@quenty/playerbinder": "14.25.7
|
|
44
|
-
"@quenty/playerutils": "8.21.
|
|
45
|
-
"@quenty/promise": "10.12.
|
|
46
|
-
"@quenty/promisemaid": "5.12.
|
|
47
|
-
"@quenty/receiptprocessing": "7.23.
|
|
48
|
-
"@quenty/remoting": "12.21.
|
|
49
|
-
"@quenty/rx": "13.20.
|
|
50
|
-
"@quenty/rxbinderutils": "14.25.7
|
|
51
|
-
"@quenty/servicebag": "11.13.
|
|
52
|
-
"@quenty/signal": "7.11.
|
|
53
|
-
"@quenty/statestack": "14.22.
|
|
54
|
-
"@quenty/string": "3.3.
|
|
55
|
-
"@quenty/table": "3.8.0",
|
|
56
|
-
"@quenty/tie": "10.26.
|
|
57
|
-
"@quenty/valueobject": "13.21.
|
|
30
|
+
"@quenty/attributeutils": "^14.20.6",
|
|
31
|
+
"@quenty/avatareditorutils": "^7.25.7",
|
|
32
|
+
"@quenty/baseobject": "^10.9.1",
|
|
33
|
+
"@quenty/binder": "^14.25.7",
|
|
34
|
+
"@quenty/brio": "^14.20.5",
|
|
35
|
+
"@quenty/cmdrservice": "^13.29.8",
|
|
36
|
+
"@quenty/enumutils": "^3.4.3",
|
|
37
|
+
"@quenty/gameconfig": "^12.33.8",
|
|
38
|
+
"@quenty/instanceutils": "^13.20.6",
|
|
39
|
+
"@quenty/loader": "^10.9.1",
|
|
40
|
+
"@quenty/maid": "^3.5.1",
|
|
41
|
+
"@quenty/marketplaceutils": "^11.13.4",
|
|
42
|
+
"@quenty/observablecollection": "^12.24.7",
|
|
43
|
+
"@quenty/playerbinder": "^14.25.7",
|
|
44
|
+
"@quenty/playerutils": "^8.21.7",
|
|
45
|
+
"@quenty/promise": "^10.12.4",
|
|
46
|
+
"@quenty/promisemaid": "^5.12.4",
|
|
47
|
+
"@quenty/receiptprocessing": "^7.23.7",
|
|
48
|
+
"@quenty/remoting": "^12.21.6",
|
|
49
|
+
"@quenty/rx": "^13.20.4",
|
|
50
|
+
"@quenty/rxbinderutils": "^14.25.7",
|
|
51
|
+
"@quenty/servicebag": "^11.13.4",
|
|
52
|
+
"@quenty/signal": "^7.11.3",
|
|
53
|
+
"@quenty/statestack": "^14.22.7",
|
|
54
|
+
"@quenty/string": "^3.3.4",
|
|
55
|
+
"@quenty/table": "^3.8.0",
|
|
56
|
+
"@quenty/tie": "^10.26.7",
|
|
57
|
+
"@quenty/valueobject": "^13.21.7"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "44e41814ddc3c14c3879320a10ed2d8e88103a4c"
|
|
60
60
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
@client
|
|
3
4
|
@class PlayerProductManagerClient
|
|
@@ -24,11 +25,27 @@ local PlayerProductManagerClient = setmetatable({}, PlayerProductManagerBase)
|
|
|
24
25
|
PlayerProductManagerClient.ClassName = "PlayerProductManagerClient"
|
|
25
26
|
PlayerProductManagerClient.__index = PlayerProductManagerClient
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
export type PlayerProductManagerClient =
|
|
29
|
+
typeof(setmetatable(
|
|
30
|
+
{} :: {
|
|
31
|
+
_obj: Player,
|
|
32
|
+
_player: Player,
|
|
33
|
+
_serviceBag: ServiceBag.ServiceBag,
|
|
34
|
+
_remoting: Remoting.Remoting,
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
_avatarEditorInventoryServiceClient: AvatarEditorInventoryServiceClient.AvatarEditorInventoryServiceClient,
|
|
37
|
+
_catalogSearchServiceCache: CatalogSearchServiceCache.CatalogSearchServiceCache,
|
|
38
|
+
},
|
|
39
|
+
{} :: typeof({ __index = PlayerProductManagerClient })
|
|
40
|
+
))
|
|
41
|
+
& PlayerProductManagerBase.PlayerProductManagerBase
|
|
42
|
+
|
|
43
|
+
function PlayerProductManagerClient.new(player: Player, serviceBag: ServiceBag.ServiceBag): PlayerProductManagerClient
|
|
44
|
+
local self: PlayerProductManagerClient =
|
|
45
|
+
setmetatable(PlayerProductManagerBase.new(player, serviceBag) :: any, PlayerProductManagerClient)
|
|
46
|
+
|
|
47
|
+
self._avatarEditorInventoryServiceClient = self._serviceBag:GetService(AvatarEditorInventoryServiceClient :: any)
|
|
48
|
+
self._catalogSearchServiceCache = self._serviceBag:GetService(CatalogSearchServiceCache :: any)
|
|
32
49
|
|
|
33
50
|
if self._obj == Players.LocalPlayer then
|
|
34
51
|
self._remoting = self._maid:Add(Remoting.new(self._obj, "PlayerProductManager", Remoting.Realms.CLIENT))
|
|
@@ -53,11 +70,11 @@ end
|
|
|
53
70
|
Gets the current player
|
|
54
71
|
@return Player
|
|
55
72
|
]=]
|
|
56
|
-
function PlayerProductManagerClient
|
|
73
|
+
function PlayerProductManagerClient.GetPlayer(self: PlayerProductManagerClient): Player
|
|
57
74
|
return self._obj
|
|
58
75
|
end
|
|
59
76
|
|
|
60
|
-
function PlayerProductManagerClient
|
|
77
|
+
function PlayerProductManagerClient._setupAssetTracker(self: PlayerProductManagerClient): ()
|
|
61
78
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.ASSET)
|
|
62
79
|
local assetOwnership = assert(tracker:GetOwnershipTracker(), "Missing ownershipTracker on client")
|
|
63
80
|
|
|
@@ -74,14 +91,18 @@ function PlayerProductManagerClient:_setupAssetTracker()
|
|
|
74
91
|
end))
|
|
75
92
|
end
|
|
76
93
|
|
|
77
|
-
function PlayerProductManagerClient
|
|
94
|
+
function PlayerProductManagerClient._setupMembershipTracker(self: PlayerProductManagerClient): ()
|
|
78
95
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.MEMBERSHIP)
|
|
79
96
|
|
|
80
97
|
self._maid:GiveTask(MarketplaceService.PromptPremiumPurchaseFinished:Connect(function()
|
|
81
|
-
|
|
98
|
+
-- TODO: Fix typing, these expect a number
|
|
99
|
+
tracker:HandlePromptClosedEvent(Enum.MembershipType.Premium :: any)
|
|
82
100
|
|
|
83
101
|
-- Not great behavior but whatever
|
|
84
|
-
tracker:HandlePurchaseEvent(
|
|
102
|
+
tracker:HandlePurchaseEvent(
|
|
103
|
+
Enum.MembershipType.Premium :: any,
|
|
104
|
+
self._obj.MembershipType == Enum.MembershipType.Premium
|
|
105
|
+
)
|
|
85
106
|
end))
|
|
86
107
|
|
|
87
108
|
-- I think this only fires on the server...
|
|
@@ -94,7 +115,7 @@ function PlayerProductManagerClient:_setupMembershipTracker()
|
|
|
94
115
|
end))
|
|
95
116
|
end
|
|
96
117
|
|
|
97
|
-
function PlayerProductManagerClient
|
|
118
|
+
function PlayerProductManagerClient._setupSubscriptionTracker(self: PlayerProductManagerClient): ()
|
|
98
119
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.SUBSCRIPTION)
|
|
99
120
|
|
|
100
121
|
-- Main event
|
|
@@ -127,7 +148,7 @@ function PlayerProductManagerClient:_setupSubscriptionTracker()
|
|
|
127
148
|
end))
|
|
128
149
|
end
|
|
129
150
|
|
|
130
|
-
function PlayerProductManagerClient
|
|
151
|
+
function PlayerProductManagerClient._connectBulkPurchaseMarketplace(self: PlayerProductManagerClient): ()
|
|
131
152
|
self._maid:GiveTask(MarketplaceService.PromptBulkPurchaseFinished:Connect(function(player, status, results)
|
|
132
153
|
if player ~= self._obj then
|
|
133
154
|
return
|
|
@@ -161,7 +182,7 @@ function PlayerProductManagerClient:_connectBulkPurchaseMarketplace()
|
|
|
161
182
|
end))
|
|
162
183
|
end
|
|
163
184
|
|
|
164
|
-
function PlayerProductManagerClient
|
|
185
|
+
function PlayerProductManagerClient._setupProductTracker(self: PlayerProductManagerClient): ()
|
|
165
186
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.PRODUCT)
|
|
166
187
|
|
|
167
188
|
self._maid:GiveTask(
|
|
@@ -185,7 +206,7 @@ function PlayerProductManagerClient:_setupProductTracker()
|
|
|
185
206
|
end))
|
|
186
207
|
end
|
|
187
208
|
|
|
188
|
-
function PlayerProductManagerClient
|
|
209
|
+
function PlayerProductManagerClient._connectGamePassTracker(self: PlayerProductManagerClient): ()
|
|
189
210
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.PASS)
|
|
190
211
|
|
|
191
212
|
self._maid:GiveTask(
|
|
@@ -202,13 +223,13 @@ function PlayerProductManagerClient:_connectGamePassTracker()
|
|
|
202
223
|
)
|
|
203
224
|
end
|
|
204
225
|
|
|
205
|
-
function PlayerProductManagerClient
|
|
226
|
+
function PlayerProductManagerClient._setupBundleTracker(self: PlayerProductManagerClient): ()
|
|
206
227
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.BUNDLE)
|
|
207
228
|
|
|
208
229
|
local bundleOwnership = assert(tracker:GetOwnershipTracker(), "Missing ownershipTracker on client")
|
|
209
230
|
|
|
210
231
|
bundleOwnership:SetQueryOwnershipCallback(function(assetId)
|
|
211
|
-
return self:_promiseBulkOwnsBundleQuery(assetId
|
|
232
|
+
return self:_promiseBulkOwnsBundleQuery(assetId)
|
|
212
233
|
end)
|
|
213
234
|
|
|
214
235
|
self._maid:GiveTask(MarketplaceService.PromptBundlePurchaseFinished:Connect(function(player, bundleId, isPurchased)
|
|
@@ -221,7 +242,7 @@ function PlayerProductManagerClient:_setupBundleTracker()
|
|
|
221
242
|
end))
|
|
222
243
|
end
|
|
223
244
|
|
|
224
|
-
function PlayerProductManagerClient
|
|
245
|
+
function PlayerProductManagerClient._promiseBulkOwnsAssetQuery(self: PlayerProductManagerClient, assetId)
|
|
225
246
|
if self._avatarEditorInventoryServiceClient:IsInventoryAccessAllowed() then
|
|
226
247
|
-- When scrolling through a ton of entries in the avatar editor we want to query
|
|
227
248
|
-- this is typically faster. We really hope we aren't the Roblox account.
|
|
@@ -230,7 +251,8 @@ function PlayerProductManagerClient:_promiseBulkOwnsAssetQuery(assetId)
|
|
|
230
251
|
:Then(function(itemDetails)
|
|
231
252
|
-- https://devforum.roblox.com/t/avatareditorservicegetitemdetails-returns-ownership-where-as-avatareditorservicegetbatchitemdetails-does-not/3257431
|
|
232
253
|
|
|
233
|
-
local assetType
|
|
254
|
+
local assetType: Enum.AvatarAssetType? =
|
|
255
|
+
EnumUtils.toEnum(Enum.AvatarAssetType, itemDetails.AssetType) :: any
|
|
234
256
|
if not assetType then
|
|
235
257
|
-- TODO: Fallback to standard query?
|
|
236
258
|
return Promise.rejected("Failed to get assetType")
|
|
@@ -247,8 +269,11 @@ function PlayerProductManagerClient:_promiseBulkOwnsAssetQuery(assetId)
|
|
|
247
269
|
return MarketplaceUtils.promisePlayerOwnsAsset(self._player, assetId)
|
|
248
270
|
end
|
|
249
271
|
|
|
250
|
-
function PlayerProductManagerClient
|
|
272
|
+
function PlayerProductManagerClient._promiseBulkOwnsBundleQuery(self: PlayerProductManagerClient, bundleId: number)
|
|
251
273
|
return MarketplaceUtils.promisePlayerOwnsBundle(self._player, bundleId)
|
|
252
274
|
end
|
|
253
275
|
|
|
254
|
-
return Binder.new(
|
|
276
|
+
return Binder.new(
|
|
277
|
+
"PlayerProductManager",
|
|
278
|
+
PlayerProductManagerClient :: any
|
|
279
|
+
) :: Binder.Binder<PlayerProductManagerClient>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!nonstrict
|
|
1
2
|
--[=[
|
|
2
3
|
Handles product prompting state on the server
|
|
3
4
|
|
|
@@ -23,6 +24,16 @@ local PlayerProductManager = setmetatable({}, PlayerProductManagerBase)
|
|
|
23
24
|
PlayerProductManager.ClassName = "PlayerProductManager"
|
|
24
25
|
PlayerProductManager.__index = PlayerProductManager
|
|
25
26
|
|
|
27
|
+
export type PlayerProductManager =
|
|
28
|
+
typeof(setmetatable(
|
|
29
|
+
{} :: {
|
|
30
|
+
_serviceBag: ServiceBag.ServiceBag,
|
|
31
|
+
_receiptProcessingService: ReceiptProcessingService.ReceiptProcessingService,
|
|
32
|
+
},
|
|
33
|
+
{} :: typeof({ __index = PlayerProductManager })
|
|
34
|
+
))
|
|
35
|
+
& PlayerProductManagerBase.PlayerProductManagerBase
|
|
36
|
+
|
|
26
37
|
--[=[
|
|
27
38
|
Managers players products and purchase state. Should be retrieved via binder.
|
|
28
39
|
|
|
@@ -30,8 +41,9 @@ PlayerProductManager.__index = PlayerProductManager
|
|
|
30
41
|
@param serviceBag ServiceBag
|
|
31
42
|
@return PlayerProductManager
|
|
32
43
|
]=]
|
|
33
|
-
function PlayerProductManager.new(player, serviceBag: ServiceBag.ServiceBag)
|
|
34
|
-
local self =
|
|
44
|
+
function PlayerProductManager.new(player: Player, serviceBag: ServiceBag.ServiceBag): PlayerProductManager
|
|
45
|
+
local self: PlayerProductManager =
|
|
46
|
+
setmetatable(PlayerProductManagerBase.new(player, serviceBag) :: any, PlayerProductManager)
|
|
35
47
|
|
|
36
48
|
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
37
49
|
self._receiptProcessingService = self._serviceBag:GetService(ReceiptProcessingService)
|
|
@@ -55,11 +67,11 @@ function PlayerProductManager.new(player, serviceBag: ServiceBag.ServiceBag)
|
|
|
55
67
|
return self
|
|
56
68
|
end
|
|
57
69
|
|
|
58
|
-
function PlayerProductManager
|
|
70
|
+
function PlayerProductManager._setupRemoting(self: PlayerProductManager): ()
|
|
59
71
|
self._remoting = self._maid:Add(Remoting.Server.new(self._obj, "PlayerProductManager", Remoting.Realms.SERVER))
|
|
60
72
|
end
|
|
61
73
|
|
|
62
|
-
function PlayerProductManager
|
|
74
|
+
function PlayerProductManager._setupAssetTracker(self: PlayerProductManager): ()
|
|
63
75
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.ASSET)
|
|
64
76
|
|
|
65
77
|
self._maid:GiveTask(self._remoting.AssetPromptPurchaseFinished:Connect(function(player, assetId, isPurchased)
|
|
@@ -73,7 +85,7 @@ function PlayerProductManager:_setupAssetTracker()
|
|
|
73
85
|
end))
|
|
74
86
|
end
|
|
75
87
|
|
|
76
|
-
function PlayerProductManager
|
|
88
|
+
function PlayerProductManager._setupProductTracker(self: PlayerProductManager): ()
|
|
77
89
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.PRODUCT)
|
|
78
90
|
|
|
79
91
|
-- Source of truth for purchase is here
|
|
@@ -105,7 +117,7 @@ function PlayerProductManager:_setupProductTracker()
|
|
|
105
117
|
)
|
|
106
118
|
end
|
|
107
119
|
|
|
108
|
-
function PlayerProductManager
|
|
120
|
+
function PlayerProductManager._setupPassTracker(self: PlayerProductManager): ()
|
|
109
121
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.PASS)
|
|
110
122
|
|
|
111
123
|
self._maid:GiveTask(self._remoting.PromptGamePassPurchaseFinished:Connect(function(player, gamePassId, isPurchased)
|
|
@@ -119,7 +131,7 @@ function PlayerProductManager:_setupPassTracker()
|
|
|
119
131
|
end))
|
|
120
132
|
end
|
|
121
133
|
|
|
122
|
-
function PlayerProductManager
|
|
134
|
+
function PlayerProductManager._setupMembershipTracker(self: PlayerProductManager): ()
|
|
123
135
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.MEMBERSHIP)
|
|
124
136
|
|
|
125
137
|
self._maid:GiveTask(Players.PlayerMembershipChanged:Connect(function(player)
|
|
@@ -131,7 +143,7 @@ function PlayerProductManager:_setupMembershipTracker()
|
|
|
131
143
|
end))
|
|
132
144
|
end
|
|
133
145
|
|
|
134
|
-
function PlayerProductManager
|
|
146
|
+
function PlayerProductManager._setupSubscriptionTracker(self: PlayerProductManager): ()
|
|
135
147
|
self._remoting.UserSubscriptionStatusChanged:DeclareEvent()
|
|
136
148
|
|
|
137
149
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.SUBSCRIPTION)
|
|
@@ -164,7 +176,7 @@ function PlayerProductManager:_setupSubscriptionTracker()
|
|
|
164
176
|
end))
|
|
165
177
|
end
|
|
166
178
|
|
|
167
|
-
function PlayerProductManager
|
|
179
|
+
function PlayerProductManager._setupBundleTracker(self: PlayerProductManager): ()
|
|
168
180
|
local tracker = self:GetAssetTrackerOrError(GameConfigAssetTypes.BUNDLE)
|
|
169
181
|
|
|
170
182
|
self._maid:GiveTask(MarketplaceService.PromptBundlePurchaseFinished:Connect(function(player, bundleId, isPurchased)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
This tracking is relatively complicated because we want to track both
|
|
3
4
|
ownership from attributes (can be customized locally), as well as async
|
|
@@ -10,6 +11,8 @@ local require = require(script.Parent.loader).load(script)
|
|
|
10
11
|
|
|
11
12
|
local BaseObject = require("BaseObject")
|
|
12
13
|
local GameConfigAssetTypeUtils = require("GameConfigAssetTypeUtils")
|
|
14
|
+
local GameConfigAssetTypes = require("GameConfigAssetTypes")
|
|
15
|
+
local GameConfigPicker = require("GameConfigPicker")
|
|
13
16
|
local Maid = require("Maid")
|
|
14
17
|
local Observable = require("Observable")
|
|
15
18
|
local ObservableSet = require("ObservableSet")
|
|
@@ -20,10 +23,30 @@ local PlayerAssetOwnershipTracker = setmetatable({}, BaseObject)
|
|
|
20
23
|
PlayerAssetOwnershipTracker.ClassName = "PlayerAssetOwnershipTracker"
|
|
21
24
|
PlayerAssetOwnershipTracker.__index = PlayerAssetOwnershipTracker
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
export type PlayerAssetOwnershipTracker =
|
|
27
|
+
typeof(setmetatable(
|
|
28
|
+
{} :: {
|
|
29
|
+
_player: Player,
|
|
30
|
+
_configPicker: any,
|
|
31
|
+
_assetType: GameConfigAssetTypes.GameConfigAssetType,
|
|
32
|
+
_marketTracker: any,
|
|
33
|
+
_ownershipCallback: ValueObject.ValueObject<(number) -> Promise.Promise<boolean> | nil>,
|
|
34
|
+
_ownedAssetIdSet: ObservableSet.ObservableSet<number>,
|
|
35
|
+
_assetOwnershipPromiseCache: { [number]: Promise.Promise<boolean> | boolean },
|
|
36
|
+
},
|
|
37
|
+
{} :: typeof({ __index = PlayerAssetOwnershipTracker })
|
|
38
|
+
))
|
|
39
|
+
& BaseObject.BaseObject
|
|
40
|
+
|
|
41
|
+
function PlayerAssetOwnershipTracker.new(
|
|
42
|
+
player: Player,
|
|
43
|
+
configPicker: GameConfigPicker.GameConfigPicker,
|
|
44
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType,
|
|
45
|
+
marketTracker: any
|
|
46
|
+
): PlayerAssetOwnershipTracker
|
|
24
47
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
25
48
|
|
|
26
|
-
local self = setmetatable(BaseObject.new(), PlayerAssetOwnershipTracker)
|
|
49
|
+
local self: PlayerAssetOwnershipTracker = setmetatable(BaseObject.new() :: any, PlayerAssetOwnershipTracker)
|
|
27
50
|
|
|
28
51
|
self._player = assert(player, "No player")
|
|
29
52
|
self._configPicker = assert(configPicker, "No configPicker")
|
|
@@ -46,7 +69,7 @@ end
|
|
|
46
69
|
Sets the callback which will query ownership
|
|
47
70
|
@param promiseOwnsAsset function
|
|
48
71
|
]=]
|
|
49
|
-
function PlayerAssetOwnershipTracker:SetQueryOwnershipCallback(promiseOwnsAsset)
|
|
72
|
+
function PlayerAssetOwnershipTracker:SetQueryOwnershipCallback(promiseOwnsAsset: (any) -> Promise.Promise<boolean>?): ()
|
|
50
73
|
assert(type(promiseOwnsAsset) == "function" or promiseOwnsAsset == nil, "Bad promiseOwnsAsset")
|
|
51
74
|
|
|
52
75
|
if self._ownershipCallback.Value == promiseOwnsAsset then
|
|
@@ -57,7 +80,7 @@ function PlayerAssetOwnershipTracker:SetQueryOwnershipCallback(promiseOwnsAsset)
|
|
|
57
80
|
self._ownershipCallback.Value = promiseOwnsAsset
|
|
58
81
|
end
|
|
59
82
|
|
|
60
|
-
function PlayerAssetOwnershipTracker:_promiseQueryAssetId(assetId: number)
|
|
83
|
+
function PlayerAssetOwnershipTracker:_promiseQueryAssetId(assetId: number): Promise.Promise<boolean>?
|
|
61
84
|
assert(type(assetId) == "number", "Bad assetId")
|
|
62
85
|
|
|
63
86
|
local promiseOwnershipCallback = self._ownershipCallback.Value
|
|
@@ -103,7 +126,7 @@ end
|
|
|
103
126
|
@param idOrKey number
|
|
104
127
|
@param ownsAsset boolean
|
|
105
128
|
]=]
|
|
106
|
-
function PlayerAssetOwnershipTracker:SetOwnership(idOrKey, ownsAsset)
|
|
129
|
+
function PlayerAssetOwnershipTracker:SetOwnership(idOrKey, ownsAsset: boolean): ()
|
|
107
130
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "idOrKey")
|
|
108
131
|
assert(type(ownsAsset) == "boolean", "Bad ownsAsset")
|
|
109
132
|
|
|
@@ -155,7 +178,7 @@ end
|
|
|
155
178
|
@param idOrKey number | number
|
|
156
179
|
@return Observable<boolean>
|
|
157
180
|
]=]
|
|
158
|
-
function PlayerAssetOwnershipTracker:ObserveOwnsAsset(idOrKey)
|
|
181
|
+
function PlayerAssetOwnershipTracker:ObserveOwnsAsset(idOrKey): Observable.Observable<boolean>
|
|
159
182
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "Bad idOrKey")
|
|
160
183
|
|
|
161
184
|
-- TODO: Get rid of several concepts here, including well known assets, attributes, and more
|
|
@@ -179,7 +202,7 @@ function PlayerAssetOwnershipTracker:ObserveOwnsAsset(idOrKey)
|
|
|
179
202
|
end))
|
|
180
203
|
|
|
181
204
|
return topMaid
|
|
182
|
-
end)
|
|
205
|
+
end) :: any
|
|
183
206
|
elseif type(idOrKey) == "number" then
|
|
184
207
|
return Observable.new(function(sub)
|
|
185
208
|
local maid = Maid.new()
|
|
@@ -193,7 +216,7 @@ function PlayerAssetOwnershipTracker:ObserveOwnsAsset(idOrKey)
|
|
|
193
216
|
end)
|
|
194
217
|
|
|
195
218
|
return maid
|
|
196
|
-
end)
|
|
219
|
+
end) :: any
|
|
197
220
|
else
|
|
198
221
|
error("Bad idOrKey")
|
|
199
222
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
Tracks a single asset type for pending purchase prompts.
|
|
3
4
|
|
|
@@ -7,10 +8,12 @@
|
|
|
7
8
|
local require = require(script.Parent.loader).load(script)
|
|
8
9
|
|
|
9
10
|
local BaseObject = require("BaseObject")
|
|
11
|
+
local Brio = require("Brio")
|
|
10
12
|
local GameConfigAssetTypeUtils = require("GameConfigAssetTypeUtils")
|
|
11
13
|
local GameConfigAssetTypes = require("GameConfigAssetTypes")
|
|
12
14
|
local Maid = require("Maid")
|
|
13
15
|
local Observable = require("Observable")
|
|
16
|
+
local PlayerAssetOwnershipTracker = require("PlayerAssetOwnershipTracker")
|
|
14
17
|
local Promise = require("Promise")
|
|
15
18
|
local Signal = require("Signal")
|
|
16
19
|
local ValueObject = require("ValueObject")
|
|
@@ -19,6 +22,28 @@ local PlayerAssetMarketTracker = setmetatable({}, BaseObject)
|
|
|
19
22
|
PlayerAssetMarketTracker.ClassName = "PlayerAssetMarketTracker"
|
|
20
23
|
PlayerAssetMarketTracker.__index = PlayerAssetMarketTracker
|
|
21
24
|
|
|
25
|
+
export type PlayerAssetMarketTracker =
|
|
26
|
+
typeof(setmetatable(
|
|
27
|
+
{} :: {
|
|
28
|
+
_assetType: GameConfigAssetTypes.GameConfigAssetType,
|
|
29
|
+
_convertIds: (string | number) -> number?,
|
|
30
|
+
_observeIdsBrio: (string | number) -> Observable.Observable<Brio.Brio<number>>,
|
|
31
|
+
_pendingPurchasePromises: { Promise.Promise<boolean> },
|
|
32
|
+
_pendingPromptOpenPromises: { Promise.Promise<boolean> },
|
|
33
|
+
_purchasedThisSession: { [number]: boolean },
|
|
34
|
+
_promptsOpenCount: ValueObject.ValueObject<number>,
|
|
35
|
+
_ownershipTracker: PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker?,
|
|
36
|
+
|
|
37
|
+
Purchased: Signal.Signal<number>,
|
|
38
|
+
PromptClosed: Signal.Signal<(number, boolean)>,
|
|
39
|
+
ShowPromptRequested: Signal.Signal<number>,
|
|
40
|
+
|
|
41
|
+
_promiseNoPromptOpen: Promise.Promise<()>?,
|
|
42
|
+
},
|
|
43
|
+
{} :: typeof({ __index = PlayerAssetMarketTracker })
|
|
44
|
+
))
|
|
45
|
+
& BaseObject.BaseObject
|
|
46
|
+
|
|
22
47
|
--[=[
|
|
23
48
|
Constructs a new market tracker. Generally you should not need to use
|
|
24
49
|
this directly.
|
|
@@ -28,10 +53,14 @@ PlayerAssetMarketTracker.__index = PlayerAssetMarketTracker
|
|
|
28
53
|
@param observeIdsBrio function
|
|
29
54
|
@return PlayerAssetMarketTracker
|
|
30
55
|
]=]
|
|
31
|
-
function PlayerAssetMarketTracker.new(
|
|
56
|
+
function PlayerAssetMarketTracker.new(
|
|
57
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType,
|
|
58
|
+
convertIds,
|
|
59
|
+
observeIdsBrio
|
|
60
|
+
): PlayerAssetMarketTracker
|
|
32
61
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
33
62
|
|
|
34
|
-
local self = setmetatable(BaseObject.new(), PlayerAssetMarketTracker)
|
|
63
|
+
local self: PlayerAssetMarketTracker = setmetatable(BaseObject.new() :: any, PlayerAssetMarketTracker)
|
|
35
64
|
|
|
36
65
|
self._assetType = assert(assetType, "No assetType")
|
|
37
66
|
self._convertIds = assert(convertIds, "No convertIds")
|
|
@@ -44,9 +73,9 @@ function PlayerAssetMarketTracker.new(assetType: GameConfigAssetTypes.GameConfig
|
|
|
44
73
|
|
|
45
74
|
self._promptsOpenCount = self._maid:Add(ValueObject.new(0, "number"))
|
|
46
75
|
|
|
47
|
-
self.Purchased = self._maid:Add(Signal.new()) -- :Fire(id)
|
|
48
|
-
self.PromptClosed = self._maid:Add(Signal.new()) -- :Fire(id, isPurchased)
|
|
49
|
-
self.ShowPromptRequested = self._maid:Add(Signal.new()) -- :Fire(id)
|
|
76
|
+
self.Purchased = self._maid:Add(Signal.new() :: any) -- :Fire(id)
|
|
77
|
+
self.PromptClosed = self._maid:Add(Signal.new() :: any) -- :Fire(id, isPurchased)
|
|
78
|
+
self.ShowPromptRequested = self._maid:Add(Signal.new() :: any) -- :Fire(id)
|
|
50
79
|
|
|
51
80
|
self._maid:GiveTask(self.Purchased:Connect(function(id)
|
|
52
81
|
self._purchasedThisSession[id] = true
|
|
@@ -65,11 +94,15 @@ function PlayerAssetMarketTracker.new(assetType: GameConfigAssetTypes.GameConfig
|
|
|
65
94
|
self._maid:GiveTask(function()
|
|
66
95
|
while #self._pendingPurchasePromises > 0 do
|
|
67
96
|
local pending = table.remove(self._pendingPurchasePromises, #self._pendingPurchasePromises)
|
|
97
|
+
assert(pending, "Typechecking assertion")
|
|
98
|
+
|
|
68
99
|
pending:Reject()
|
|
69
100
|
end
|
|
70
101
|
|
|
71
102
|
while #self._pendingPromptOpenPromises > 0 do
|
|
72
103
|
local pending = table.remove(self._pendingPromptOpenPromises, #self._pendingPromptOpenPromises)
|
|
104
|
+
assert(pending, "Typechecking assertion")
|
|
105
|
+
|
|
73
106
|
pending:Reject()
|
|
74
107
|
end
|
|
75
108
|
end)
|
|
@@ -82,7 +115,7 @@ end
|
|
|
82
115
|
|
|
83
116
|
@return Observable<number>
|
|
84
117
|
]=]
|
|
85
|
-
function PlayerAssetMarketTracker
|
|
118
|
+
function PlayerAssetMarketTracker.ObservePromptOpenCount(self: PlayerAssetMarketTracker): Observable.Observable<number>
|
|
86
119
|
return self._promptsOpenCount:Observe()
|
|
87
120
|
end
|
|
88
121
|
|
|
@@ -92,7 +125,10 @@ end
|
|
|
92
125
|
@param idOrKey string | number
|
|
93
126
|
@return Observable<()>
|
|
94
127
|
]=]
|
|
95
|
-
function PlayerAssetMarketTracker
|
|
128
|
+
function PlayerAssetMarketTracker.ObserveAssetPurchased(
|
|
129
|
+
self: PlayerAssetMarketTracker,
|
|
130
|
+
idOrKey: string | number
|
|
131
|
+
): Observable.Observable<()>
|
|
96
132
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "Bad idOrKey")
|
|
97
133
|
|
|
98
134
|
return Observable.new(function(sub)
|
|
@@ -132,7 +168,9 @@ end
|
|
|
132
168
|
|
|
133
169
|
@return GetOwnershipTracker
|
|
134
170
|
]=]
|
|
135
|
-
function PlayerAssetMarketTracker
|
|
171
|
+
function PlayerAssetMarketTracker.GetOwnershipTracker(
|
|
172
|
+
self: PlayerAssetMarketTracker
|
|
173
|
+
): PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker?
|
|
136
174
|
return self._ownershipTracker
|
|
137
175
|
end
|
|
138
176
|
|
|
@@ -143,7 +181,10 @@ end
|
|
|
143
181
|
@param idOrKey number | string
|
|
144
182
|
@return Promise<boolean>
|
|
145
183
|
]=]
|
|
146
|
-
function PlayerAssetMarketTracker
|
|
184
|
+
function PlayerAssetMarketTracker.PromisePromptPurchase(
|
|
185
|
+
self: PlayerAssetMarketTracker,
|
|
186
|
+
idOrKey: string | number
|
|
187
|
+
): Promise.Promise<boolean>
|
|
147
188
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "Bad idOrKey")
|
|
148
189
|
|
|
149
190
|
local id = self._convertIds(idOrKey)
|
|
@@ -202,7 +243,7 @@ function PlayerAssetMarketTracker:PromisePromptPurchase(idOrKey: string | number
|
|
|
202
243
|
end
|
|
203
244
|
|
|
204
245
|
do
|
|
205
|
-
local promptOpenPromise = Promise.new()
|
|
246
|
+
local promptOpenPromise: Promise.Promise<boolean> = Promise.new()
|
|
206
247
|
self._pendingPromptOpenPromises[id] = promptOpenPromise
|
|
207
248
|
|
|
208
249
|
self._promptsOpenCount.Value = self._promptsOpenCount.Value + 1
|
|
@@ -215,7 +256,7 @@ function PlayerAssetMarketTracker:PromisePromptPurchase(idOrKey: string | number
|
|
|
215
256
|
end
|
|
216
257
|
|
|
217
258
|
-- Make sure to do promise here so we can't double-open prompts
|
|
218
|
-
local purchasePromise = Promise.new()
|
|
259
|
+
local purchasePromise: Promise.Promise<boolean> = Promise.new()
|
|
219
260
|
self._pendingPurchasePromises[id] = purchasePromise
|
|
220
261
|
|
|
221
262
|
purchasePromise:Finally(function()
|
|
@@ -235,7 +276,10 @@ end
|
|
|
235
276
|
|
|
236
277
|
@param ownershipTracker PlayerAssetOwnershipTracker
|
|
237
278
|
]=]
|
|
238
|
-
function PlayerAssetMarketTracker
|
|
279
|
+
function PlayerAssetMarketTracker.SetOwnershipTracker(
|
|
280
|
+
self: PlayerAssetMarketTracker,
|
|
281
|
+
ownershipTracker: PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker?
|
|
282
|
+
): ()
|
|
239
283
|
assert(type(ownershipTracker) == "table" or ownershipTracker == nil, "Bad ownershipTracker")
|
|
240
284
|
|
|
241
285
|
self._ownershipTracker = ownershipTracker
|
|
@@ -246,7 +290,7 @@ end
|
|
|
246
290
|
|
|
247
291
|
@return GameConfigAssetTypes
|
|
248
292
|
]=]
|
|
249
|
-
function PlayerAssetMarketTracker
|
|
293
|
+
function PlayerAssetMarketTracker.GetAssetType(self: PlayerAssetMarketTracker): GameConfigAssetTypes.GameConfigAssetType
|
|
250
294
|
return self._assetType
|
|
251
295
|
end
|
|
252
296
|
|
|
@@ -256,7 +300,10 @@ end
|
|
|
256
300
|
@param idOrKey string | number
|
|
257
301
|
@return boolean
|
|
258
302
|
]=]
|
|
259
|
-
function PlayerAssetMarketTracker
|
|
303
|
+
function PlayerAssetMarketTracker.HasPurchasedThisSession(
|
|
304
|
+
self: PlayerAssetMarketTracker,
|
|
305
|
+
idOrKey: string | number
|
|
306
|
+
): boolean
|
|
260
307
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "idOrKey")
|
|
261
308
|
|
|
262
309
|
local id = self._convertIds(idOrKey)
|
|
@@ -277,7 +324,7 @@ end
|
|
|
277
324
|
|
|
278
325
|
@return boolean
|
|
279
326
|
]=]
|
|
280
|
-
function PlayerAssetMarketTracker
|
|
327
|
+
function PlayerAssetMarketTracker.IsPromptOpen(self: PlayerAssetMarketTracker): boolean
|
|
281
328
|
return self._promptsOpenCount.Value > 0
|
|
282
329
|
end
|
|
283
330
|
|
|
@@ -287,11 +334,15 @@ end
|
|
|
287
334
|
@param id number
|
|
288
335
|
@param isPurchased boolean
|
|
289
336
|
]=]
|
|
290
|
-
function PlayerAssetMarketTracker
|
|
337
|
+
function PlayerAssetMarketTracker.HandlePurchaseEvent(
|
|
338
|
+
self: PlayerAssetMarketTracker,
|
|
339
|
+
id: number,
|
|
340
|
+
isPurchased: boolean
|
|
341
|
+
): ()
|
|
291
342
|
assert(type(id) == "number", "Bad id")
|
|
292
343
|
assert(type(isPurchased) == "boolean", "Bad isPurchased")
|
|
293
344
|
|
|
294
|
-
local purchasePromise = self._pendingPurchasePromises[id] or Promise.new()
|
|
345
|
+
local purchasePromise: any = self._pendingPurchasePromises[id] or Promise.new()
|
|
295
346
|
|
|
296
347
|
if isPurchased then
|
|
297
348
|
self.Purchased:Fire(id)
|
|
@@ -305,10 +356,10 @@ end
|
|
|
305
356
|
|
|
306
357
|
@param id number
|
|
307
358
|
]=]
|
|
308
|
-
function PlayerAssetMarketTracker
|
|
359
|
+
function PlayerAssetMarketTracker.HandlePromptClosedEvent(self: PlayerAssetMarketTracker, id: number): ()
|
|
309
360
|
assert(type(id) == "number", "Bad id")
|
|
310
361
|
|
|
311
|
-
local promptOpenPromise = self._pendingPromptOpenPromises[id] or Promise.new()
|
|
362
|
+
local promptOpenPromise: any = self._pendingPromptOpenPromises[id] or Promise.new()
|
|
312
363
|
promptOpenPromise:Resolve()
|
|
313
364
|
end
|
|
314
365
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
See [PlayerProductManager] and [PlayerProductManagerClient]
|
|
3
4
|
|
|
@@ -13,6 +14,7 @@ local GameConfigAssetTypeUtils = require("GameConfigAssetTypeUtils")
|
|
|
13
14
|
local GameConfigAssetTypes = require("GameConfigAssetTypes")
|
|
14
15
|
local GameConfigDataService = require("GameConfigDataService")
|
|
15
16
|
local MarketplaceUtils = require("MarketplaceUtils")
|
|
17
|
+
local Observable = require("Observable")
|
|
16
18
|
local PlayerAssetMarketTracker = require("PlayerAssetMarketTracker")
|
|
17
19
|
local PlayerAssetMarketTrackerInterface = require("PlayerAssetMarketTrackerInterface")
|
|
18
20
|
local PlayerAssetOwnershipTracker = require("PlayerAssetOwnershipTracker")
|
|
@@ -26,6 +28,27 @@ local PlayerProductManagerBase = setmetatable({}, BaseObject)
|
|
|
26
28
|
PlayerProductManagerBase.ClassName = "PlayerProductManagerBase"
|
|
27
29
|
PlayerProductManagerBase.__index = PlayerProductManagerBase
|
|
28
30
|
|
|
31
|
+
export type PlayerProductManagerBase =
|
|
32
|
+
typeof(setmetatable(
|
|
33
|
+
{} :: {
|
|
34
|
+
_serviceBag: ServiceBag.ServiceBag,
|
|
35
|
+
_obj: Player,
|
|
36
|
+
_player: Player,
|
|
37
|
+
_tieRealmService: TieRealmService.TieRealmService,
|
|
38
|
+
_gameConfigDataService: GameConfigDataService.GameConfigDataService,
|
|
39
|
+
_configPicker: any,
|
|
40
|
+
_assetMarketTrackers: {
|
|
41
|
+
[GameConfigAssetTypes.GameConfigAssetType]: PlayerAssetMarketTracker.PlayerAssetMarketTracker,
|
|
42
|
+
},
|
|
43
|
+
_ownershipTrackers: {
|
|
44
|
+
[GameConfigAssetTypes.GameConfigAssetType]: PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker,
|
|
45
|
+
},
|
|
46
|
+
_observeNextNoPromptOpen: Observable.Observable<boolean>?,
|
|
47
|
+
},
|
|
48
|
+
{} :: typeof({ __index = PlayerProductManagerBase })
|
|
49
|
+
))
|
|
50
|
+
& BaseObject.BaseObject
|
|
51
|
+
|
|
29
52
|
--[=[
|
|
30
53
|
Constructs a new PlayerProductManagerBase, which provides helper methods for
|
|
31
54
|
the PlayerProductManager.
|
|
@@ -34,14 +57,14 @@ PlayerProductManagerBase.__index = PlayerProductManagerBase
|
|
|
34
57
|
@param serviceBag ServiceBag
|
|
35
58
|
@return PlayerProductManagerBase
|
|
36
59
|
]=]
|
|
37
|
-
function PlayerProductManagerBase.new(player, serviceBag: ServiceBag.ServiceBag)
|
|
38
|
-
local self = setmetatable(BaseObject.new(player), PlayerProductManagerBase)
|
|
60
|
+
function PlayerProductManagerBase.new(player: Player, serviceBag: ServiceBag.ServiceBag): PlayerProductManagerBase
|
|
61
|
+
local self: PlayerProductManagerBase = setmetatable(BaseObject.new(player) :: any, PlayerProductManagerBase)
|
|
39
62
|
|
|
40
63
|
self._player = assert(player, "No player")
|
|
41
64
|
|
|
42
65
|
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
43
|
-
self._tieRealmService = self._serviceBag:GetService(TieRealmService)
|
|
44
|
-
self._gameConfigDataService = self._serviceBag:GetService(GameConfigDataService)
|
|
66
|
+
self._tieRealmService = self._serviceBag:GetService(TieRealmService :: any)
|
|
67
|
+
self._gameConfigDataService = self._serviceBag:GetService(GameConfigDataService :: any)
|
|
45
68
|
|
|
46
69
|
self._configPicker = self._gameConfigDataService:GetConfigPicker()
|
|
47
70
|
|
|
@@ -79,7 +102,9 @@ function PlayerProductManagerBase.new(player, serviceBag: ServiceBag.ServiceBag)
|
|
|
79
102
|
MarketplaceService:PromptSubscriptionPurchase(self._player, subscriptionId)
|
|
80
103
|
end))
|
|
81
104
|
|
|
82
|
-
self._maid:GiveTask(membership.ShowPromptRequested:Connect(function(membershipType)
|
|
105
|
+
self._maid:GiveTask(membership.ShowPromptRequested:Connect(function(membershipType: any)
|
|
106
|
+
-- TODO: membershipType is not a number and checking is wrong
|
|
107
|
+
|
|
83
108
|
if membershipType == Enum.MembershipType.Premium then
|
|
84
109
|
MarketplaceService:PromptPremiumPurchase(self._player)
|
|
85
110
|
else
|
|
@@ -121,8 +146,8 @@ function PlayerProductManagerBase.new(player, serviceBag: ServiceBag.ServiceBag)
|
|
|
121
146
|
return self
|
|
122
147
|
end
|
|
123
148
|
|
|
124
|
-
function PlayerProductManagerBase
|
|
125
|
-
for assetType, assetMarketTracker in self._assetMarketTrackers do
|
|
149
|
+
function PlayerProductManagerBase.ExportMarketTrackers(self: PlayerProductManagerBase, parent)
|
|
150
|
+
for assetType: GameConfigAssetTypes.GameConfigAssetType, assetMarketTracker in self._assetMarketTrackers do
|
|
126
151
|
local folder = self._maid:Add(Instance.new("Folder"))
|
|
127
152
|
folder.Name = String.toCamelCase(GameConfigAssetTypeUtils.getPlural(assetType))
|
|
128
153
|
folder.Archivable = false
|
|
@@ -139,7 +164,7 @@ end
|
|
|
139
164
|
Gets the current player
|
|
140
165
|
@return Player
|
|
141
166
|
]=]
|
|
142
|
-
function PlayerProductManagerBase
|
|
167
|
+
function PlayerProductManagerBase.GetPlayer(self: PlayerProductManagerBase): Player
|
|
143
168
|
return self._obj
|
|
144
169
|
end
|
|
145
170
|
|
|
@@ -148,7 +173,7 @@ end
|
|
|
148
173
|
@param assetType GameConfigAssetType
|
|
149
174
|
@return PlayerAssetMarketTracker
|
|
150
175
|
]=]
|
|
151
|
-
function PlayerProductManagerBase
|
|
176
|
+
function PlayerProductManagerBase.IsOwnable(self: PlayerProductManagerBase, assetType): boolean
|
|
152
177
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
153
178
|
|
|
154
179
|
return self._ownershipTrackers[assetType] ~= nil
|
|
@@ -159,8 +184,8 @@ end
|
|
|
159
184
|
|
|
160
185
|
@return boolean
|
|
161
186
|
]=]
|
|
162
|
-
function PlayerProductManagerBase
|
|
163
|
-
for _, assetTracker in self._assetMarketTrackers do
|
|
187
|
+
function PlayerProductManagerBase.IsPromptOpen(self: PlayerProductManagerBase): boolean
|
|
188
|
+
for _, assetTracker: any in self._assetMarketTrackers do
|
|
164
189
|
if assetTracker:IsPromptOpen() then
|
|
165
190
|
return true
|
|
166
191
|
end
|
|
@@ -174,18 +199,18 @@ end
|
|
|
174
199
|
|
|
175
200
|
@return Promise
|
|
176
201
|
]=]
|
|
177
|
-
function PlayerProductManagerBase
|
|
202
|
+
function PlayerProductManagerBase.PromisePlayerPromptClosed(self: PlayerProductManagerBase): Promise.Promise<()>
|
|
178
203
|
if not self:IsPromptOpen() then
|
|
179
204
|
return Promise.resolved()
|
|
180
205
|
end
|
|
181
206
|
|
|
182
207
|
if self._observeNextNoPromptOpen then
|
|
183
|
-
return Rx.toPromise(self._observeNextNoPromptOpen)
|
|
208
|
+
return Rx.toPromise(self._observeNextNoPromptOpen :: any)
|
|
184
209
|
end
|
|
185
210
|
|
|
186
211
|
local observeOpenCounts = {}
|
|
187
212
|
|
|
188
|
-
for assetType, assetTracker in self._assetMarketTrackers do
|
|
213
|
+
for assetType, assetTracker: any in self._assetMarketTrackers do
|
|
189
214
|
observeOpenCounts[assetType] = assetTracker:ObservePromptOpenCount()
|
|
190
215
|
end
|
|
191
216
|
|
|
@@ -198,15 +223,15 @@ function PlayerProductManagerBase:PromisePlayerPromptClosed()
|
|
|
198
223
|
end
|
|
199
224
|
|
|
200
225
|
return true
|
|
201
|
-
end),
|
|
226
|
+
end) :: any,
|
|
202
227
|
Rx.where(function(value)
|
|
203
228
|
return value
|
|
204
|
-
end),
|
|
205
|
-
Rx.distinct(),
|
|
206
|
-
Rx.share(),
|
|
207
|
-
})
|
|
229
|
+
end) :: any,
|
|
230
|
+
Rx.distinct() :: any,
|
|
231
|
+
Rx.share() :: any,
|
|
232
|
+
}) :: any
|
|
208
233
|
|
|
209
|
-
return Rx.toPromise(self._observeNextNoPromptOpen)
|
|
234
|
+
return Rx.toPromise(self._observeNextNoPromptOpen :: any)
|
|
210
235
|
end
|
|
211
236
|
|
|
212
237
|
--[=[
|
|
@@ -215,7 +240,10 @@ end
|
|
|
215
240
|
@param assetType GameConfigAssetType
|
|
216
241
|
@return PlayerAssetMarketTracker
|
|
217
242
|
]=]
|
|
218
|
-
function PlayerProductManagerBase
|
|
243
|
+
function PlayerProductManagerBase.GetAssetTrackerOrError(
|
|
244
|
+
self: PlayerProductManagerBase,
|
|
245
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType
|
|
246
|
+
): PlayerAssetMarketTracker.PlayerAssetMarketTracker
|
|
219
247
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
220
248
|
|
|
221
249
|
local assetTracker = self._assetMarketTrackers[assetType]
|
|
@@ -231,7 +259,10 @@ end
|
|
|
231
259
|
@param assetType GameConfigAssetType
|
|
232
260
|
@return PlayerAssetMarketTracker
|
|
233
261
|
]=]
|
|
234
|
-
function PlayerProductManagerBase
|
|
262
|
+
function PlayerProductManagerBase.GetOwnershipTrackerOrError(
|
|
263
|
+
self: PlayerProductManagerBase,
|
|
264
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType
|
|
265
|
+
): PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker
|
|
235
266
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
236
267
|
|
|
237
268
|
local assetTracker = self._ownershipTrackers[assetType]
|
|
@@ -241,7 +272,10 @@ function PlayerProductManagerBase:GetOwnershipTrackerOrError(assetType)
|
|
|
241
272
|
return assetTracker
|
|
242
273
|
end
|
|
243
274
|
|
|
244
|
-
function PlayerProductManagerBase
|
|
275
|
+
function PlayerProductManagerBase._addOwnershipTracker(
|
|
276
|
+
self: PlayerProductManagerBase,
|
|
277
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType
|
|
278
|
+
): PlayerAssetOwnershipTracker.PlayerAssetOwnershipTracker
|
|
245
279
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
246
280
|
assert(not self._ownershipTrackers[assetType], "Already have ownership tracker")
|
|
247
281
|
|
|
@@ -256,7 +290,10 @@ function PlayerProductManagerBase:_addOwnershipTracker(assetType)
|
|
|
256
290
|
return ownershipTracker
|
|
257
291
|
end
|
|
258
292
|
|
|
259
|
-
function PlayerProductManagerBase
|
|
293
|
+
function PlayerProductManagerBase._addAssetTracker(
|
|
294
|
+
self: PlayerProductManagerBase,
|
|
295
|
+
assetType: GameConfigAssetTypes.GameConfigAssetType
|
|
296
|
+
): PlayerAssetMarketTracker.PlayerAssetMarketTracker
|
|
260
297
|
assert(GameConfigAssetTypeUtils.isAssetType(assetType), "Bad assetType")
|
|
261
298
|
assert(not self._assetMarketTrackers[assetType], "Already have tracker")
|
|
262
299
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--!nonstrict
|
|
1
2
|
--[[
|
|
2
3
|
@class ServerMain
|
|
3
4
|
]]
|
|
@@ -19,7 +20,7 @@ serviceBag:GetService(require("GameConfigService")):AddAsset("FrogOnHead", 45565
|
|
|
19
20
|
|
|
20
21
|
local GameConfigAssetTypes = require("GameConfigAssetTypes")
|
|
21
22
|
|
|
22
|
-
local function makePrompt(assetType, idOrKey, cframe)
|
|
23
|
+
local function makePrompt(assetType: GameConfigAssetTypes.GameConfigAssetType, idOrKey: number | string, cframe: CFrame)
|
|
23
24
|
assert(type(idOrKey) == "number" or type(idOrKey) == "string", "Bad idOrKey")
|
|
24
25
|
|
|
25
26
|
local promptPart = Instance.new("Part")
|