Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Users/quenty/sorted list improvements #522

Merged
merged 30 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9883437
fix: Subscription status is reported properly
Quenty Nov 13, 2024
637d0ae
docs: Update docsfor the PlayerAssetMarketTracker
Quenty Nov 13, 2024
8afb7cc
feat: Add PagesProxy to allow caching of pages
Quenty Nov 13, 2024
aaa3779
refactor: Move aggregation logic into shared module
Quenty Nov 13, 2024
9d2390f
docs: Fix receipt processing docs
Quenty Nov 13, 2024
8995ffc
fix: Reject promises when failing to succeed prompt
Quenty Nov 13, 2024
0232f25
feat: Use EnumUtils here
Quenty Nov 13, 2024
939f8b1
feat: Break up logic into inventory and catalog to allow centralized …
Quenty Nov 13, 2024
4dffc3c
feat: Add funnels helper package
Quenty Nov 14, 2024
8577179
docs: Update docs
Quenty Nov 14, 2024
d159eea
feat: PlayerProductManagerClient queries inventory when inventory is …
Quenty Nov 14, 2024
f1c068d
fix: ObservableSortedList fires removed indexes (note: Doesn't handle…
Quenty Nov 14, 2024
aecd3a5
docs: Add articles to binder README.md
Quenty Nov 18, 2024
5147d50
feat: Remove ownership tracking mess with well-known assets and attri…
Quenty Nov 18, 2024
dae065f
refactor: Optimize switchMap and flatMap calls to use less maids, and…
Quenty Nov 24, 2024
b5d379b
style: Remove unused imports
Quenty Nov 24, 2024
61c9b97
feat: Add PlayerUtils.formatDisplayName(name) and other useful methods
Quenty Dec 3, 2024
e6b0838
feat: Add BoundingBox API calls
Quenty Dec 3, 2024
c07db09
feat: Add UGCSanitize to FirstPersonTransparency
Quenty Dec 3, 2024
92ea9de
fix: Fix missing services
Quenty Dec 3, 2024
a605933
fix: Fix username query
Quenty Dec 3, 2024
afb4337
fix: Symbols should be newproxy()
Quenty Dec 3, 2024
bc4fb74
feat: Add RateAggregator
Quenty Dec 3, 2024
2eafecc
fix: Fix missing dependencies
Quenty Dec 3, 2024
f7f07f7
docs: Add docs to aggregator class
Quenty Dec 3, 2024
b4b9047
fix: Use modern Roblox APIs
Quenty Dec 3, 2024
52a0cf9
fix: Use enum:FromValue and enum:FromName API methods
Quenty Dec 3, 2024
8544c2b
feat: Return a cleanup method, even when amount is 0
Quenty Dec 3, 2024
03fd05a
feat: Add :SetValue() behavior to cleanup past mounted sub and return…
Quenty Dec 3, 2024
1d2faf4
docs: Fix missing docs
Quenty Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function UIConverterUtils.toLuaPropertyString(value, debugHint)
roundY,
roundZ)
else
return string.format("CFrame.new(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", applyToTuple(roundNumber, value:components()))
return string.format("CFrame.new(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", applyToTuple(roundNumber, value:GetComponents()))
end
end
elseif valueType == "Rect" then
Expand Down
13 changes: 8 additions & 5 deletions readme.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/accessorytypeutils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Quenty"
],
"dependencies": {
"@quenty/enumutils": "file:../enumutils",
"@quenty/loader": "file:../loader"
},
"publishConfig": {
Expand Down
26 changes: 8 additions & 18 deletions src/accessorytypeutils/src/Shared/AccessoryTypeUtils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

local require = require(script.Parent.loader).load(script)

local EnumUtils = require("EnumUtils")

local AvatarEditorService = game:GetService("AvatarEditorService")

local AccessoryTypeUtils = {}
Expand Down Expand Up @@ -40,34 +42,22 @@ end
@param assetTypeId number
@return AssetType | nl
]=]
function AccessoryTypeUtils.convertAssetTypeIdToAssetType(assetTypeId): AssetType
function AccessoryTypeUtils.convertAssetTypeIdToAssetType(assetTypeId: number): AssetType?
assert(type(assetTypeId) == "number", "Bad assetTypeId")

for _, enumItem in pairs(Enum.AssetType:GetEnumItems()) do
if enumItem.Value == assetTypeId then
return enumItem
end
end

return nil
return EnumUtils.toEnum(Enum.AssetType, assetTypeId)
end

--[=[
Converts an enum value (retrieved from MarketplaceService) into a proper enum if possible

@param assetTypeId number
@param avatarAssetTypeId number
@return AvatarAssetType | nil
]=]
function AccessoryTypeUtils.convertAssetTypeIdToAvatarAssetType(assetTypeId): AvatarAssetType
assert(type(assetTypeId) == "number", "Bad assetTypeId")

for _, enumItem in pairs(Enum.AvatarAssetType:GetEnumItems()) do
if enumItem.Value == assetTypeId then
return enumItem
end
end
function AccessoryTypeUtils.convertAssetTypeIdToAvatarAssetType(avatarAssetTypeId: number): AvatarAssetType?
assert(type(avatarAssetTypeId) == "number", "Bad avatarAssetTypeId")

return nil
return EnumUtils.toEnum(Enum.AvatarAssetType, avatarAssetTypeId)
end

return AccessoryTypeUtils
25 changes: 25 additions & 0 deletions src/adorneeboundingbox/src/Shared/AdorneeBoundingBox.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ function AdorneeBoundingBox:SetAdornee(adornee)
end
end

function AdorneeBoundingBox:ObserveBoundingBox()
return Rx.combineLatest({
CFrame = self:ObserveCFrame();
Size = self:ObserveSize();
}):Pipe({
Rx.where(function(state)
return state.CFrame and state.Size
end);
})
end

function AdorneeBoundingBox:GetBoundingBox()
local cframe = self._bbCFrame.Value
local size = self._bbSize.Value

if cframe and size then
return {
CFrame = cframe;
Size = size;
}
else
return nil
end
end

--[=[
Observes the cframe of the adornee
@return Observable<Vector3>
Expand Down
2 changes: 1 addition & 1 deletion src/adorneeutils/src/Shared/AdorneeUtils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function AdorneeUtils.getCenter(adornee)
if adornee:IsA("BasePart") then
return adornee.Position
elseif adornee:IsA("Model") then
return adornee:GetBoundingBox().p
return adornee:GetBoundingBox().Position
elseif adornee:IsA("Attachment") then
return adornee.WorldPosition
elseif adornee:IsA("Humanoid") then
Expand Down
23 changes: 23 additions & 0 deletions src/aggregator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Aggregator

<div align="center">
<a href="http://quenty.github.io/NevermoreEngine/">
<img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/docs.yml/badge.svg" alt="Documentation status" />
</a>
<a href="https://discord.gg/mhtGUS8">
<img src="https://img.shields.io/discord/385151591524597761?color=5865F2&label=discord&logo=discord&logoColor=white" alt="Discord" />
</a>
<a href="https://github.com/Quenty/NevermoreEngine/actions">
<img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/build.yml/badge.svg" alt="Build and release status" />
</a>
</div>

Aggregates async promise requests

<div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/AggregatorUtils">View docs →</a></div>

## Installation

```
npm install @quenty/aggregator --save
```
7 changes: 7 additions & 0 deletions src/aggregator/default.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "aggregator",
"globIgnorePaths": [ "**/.package-lock.json" ],
"tree": {
"$path": "src"
}
}
39 changes: 39 additions & 0 deletions src/aggregator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@quenty/aggregator",
"version": "1.0.0",
"description": "Aggregates async promise requests",
"keywords": [
"Roblox",
"Nevermore",
"Lua",
"aggregator"
],
"bugs": {
"url": "https://github.com/Quenty/NevermoreEngine/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/Quenty/NevermoreEngine.git",
"directory": "src/aggregator/"
},
"funding": {
"type": "patreon",
"url": "https://www.patreon.com/quenty"
},
"license": "MIT",
"contributors": [
"Quenty"
],
"dependencies": {
"@quenty/baseobject": "file:../baseobject",
"@quenty/loader": "file:../loader",
"@quenty/lrucache": "file:../lrucache",
"@quenty/promise": "file:../promise",
"@quenty/queue": "file:../queue",
"@quenty/rx": "file:../rx",
"@quenty/tuple": "file:../tuple"
},
"publishConfig": {
"access": "public"
}
}
146 changes: 146 additions & 0 deletions src/aggregator/src/Shared/Aggregator.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
--[=[
Aggregates all requests into one big send request to deduplicate the request

@class Aggregator
]=]

local require = require(script.Parent.loader).load(script)

local BaseObject = require("BaseObject")
local Promise = require("Promise")
local Rx = require("Rx")
local LRUCache = require("LRUCache")

local Aggregator = setmetatable({}, BaseObject)
Aggregator.ClassName = "Aggregator"
Aggregator.__index = Aggregator

--[=[
Creates a new aggregator that aggregates promised results together

@param debugName string
@param promiseBulkQuery ({ number }) -> Promise<T>

@return Aggregator<T>
]=]
function Aggregator.new(debugName, promiseBulkQuery)
assert(type(debugName) == "string", "Bad debugName")

local self = setmetatable(BaseObject.new(), Aggregator)

self._debugName = debugName
self._promiseBulkQuery = assert(promiseBulkQuery, "No promiseBulkQuery")

-- TODO: LRU cache this? Limit to 1k or something?
self._promisesLruCache = LRUCache.new(2000)

self._maxPerRequest = 200
self._unsentCount = 0
self._unsentPromises = {}

return self
end

--[=[
@param id number
@return Promise<T>
]=]
function Aggregator:Promise(id)
assert(type(id) == "number", "Bad id")

local found = self._promisesLruCache:get(id)
if found then
return found
end

local promise = Promise.new()

self._unsentPromises[id] = promise
self._unsentCount = self._unsentCount + 1
self._promisesLruCache:set(id, promise)

self:_queueAggregatedPromises()

return promise
end

--[=[
Observes the aggregated data

@param id number
@return Observable<T>
]=]
function Aggregator:Observe(id)
assert(type(id) == "number", "Bad id")

return Rx.fromPromise(self:Promise(id))
end

function Aggregator:_sendAggregatedPromises(promiseMap)
assert(promiseMap, "No promiseMap")

local idList = {}
local unresolvedMap = {}
for id, promise in pairs(promiseMap) do
table.insert(idList, id)
unresolvedMap[id] = promise
end

if #idList == 0 then
return
end

assert(#idList <= self._maxPerRequest, "Too many idList sent")

self._maid:GivePromise(self._promiseBulkQuery(idList))
:Then(function(result)
assert(type(result) == "table", "Bad result")

for _, data in pairs(result) do
assert(type(data.Id) == "number", "Bad result[?].Id")

if unresolvedMap[data.Id] then
unresolvedMap[data.Id]:Resolve(data)
unresolvedMap[data.Id] = nil
end
end

-- Reject other ones
for id, promise in pairs(unresolvedMap) do
promise:Reject(string.format("Aggregated %s failed to get result for id %d", self._debugName, id))
end
end, function(...)
for _, item in pairs(unresolvedMap) do
item:Reject(...)
end
end)
end

function Aggregator:_resetQueue()
local promiseMap = self._unsentPromises

self._maid._queue = nil
self._unsentCount = 0
self._unsentPromises = {}

return promiseMap
end

function Aggregator:_queueAggregatedPromises()
if self._unsentCount >= self._maxPerRequest then
self:_sendAggregatedPromises(self:_resetQueue())
return
end

if self._maid._queue then
return
end

self._maid._queue = task.delay(0.1, function()
task.spawn(function()
self:_sendAggregatedPromises(self:_resetQueue())
end)
end)
end

return Aggregator
Loading
Loading