I’m currently working on implementing a workshop feature in my game, but I’ve encountered a challenge. At the moment, all the builds are loaded onto a single page, which could become problematic as more players start uploading to the workshop once it leaves the test place. To address this, I’m looking for a solution that allows me to sort the vehicles based on the number of downloads, with 8 vehicles per page.
I’ve already implemented a system that sorts the builds from greatest to least in terms of downloads. However, I haven’t been able to split them into separate pages while maintaining the overall sorting order. If I simply split the builds, the sorting system will only apply to each individual page and won’t consider the entire set of builds. For example, page one may have builds {75, 54, 32}, while page two has builds {95, 92, 23}.
Currently, I’m using a table to store all the build IDs. To retrieve a build’s information, including the number of downloads, I make use of GetAsync on a datastore with the corresponding build ID. However, I want to avoid going through each ID and its data every time the menu needs to reload, as this would cause significant server lag and negatively impact performance.
I would greatly appreciate it if anyone has a method or approach that can help me achieve this goal within the given constraints. Thank you in advance for your suggestions and assistance.
My recommendation is to use an Ordered Data Store to store the builds in order. What I mean is for every build that’s created, the key would be a unique id (say an incremented integer), and the value would be how many downloads it has. You can then get pages from the OrderedDatastore in ascending order and in pages of 8 to get the build keys.
When a build is saved, first an id is created, then a new entry is saved to the OrderedDataStore with the id for the key, and 0 for the value. Then, an entry is saved to a normal datastore with the id for the key but the build itself for the value.
This allows you to load a page from the OrderedDataStore, pick one of the keys, and then load the build from that key.
Now we have to allow the client to page through the data.
First, create a table on the server for holding the ids of builds. Then, every time the client wants a page of builds, first we check the table to see if their builds are already loaded. For any given page the builds needed will be 8x to 8x+8, with x being the page number. If we don’t have those builds, we get the next page in the OrderedDataStore and add the keys to the table. Now that we have the builds, we can send them to the client. Whenever the client clicks on a build, it’ll send the server the index of the build, which allows the server to find the key the client wants, which in turn allows the build to be loaded.
Hope you understood all that; feel free to reply if any help is needed implementing this or something similar.
Hello, thank you for your answer. However, I don’t think your solution will help out because the spawned (downloads) value is stored in a table inside the datastore. This is what is looks like:
Information = {
UserId = plr.UserId,
Status = "awaiting_approval",
Visibility = "public",
Title = title,
Description = description,
Thumbnail = "rbxassetid://13471315827",
Tags = {"fp","flightpoint"},
Categories = {
"All",
},
Created = {
Data = os.time(),
WorkshopVersion = 1,
},
DataVersion = {
Number = 1,
LastEdited = os.time(),
},
Build = format,
},
Data = {
Rating = 0,
Spawns = 0,
Views = 0,
Comments = {},
},
This is actually just fine, and still allows you to implement my method (if you want to). The downloads can both be saved inside of the main datastore and inside of the ordereddatastore. If you already have saved data that you need, you can loop through all of the existing builds and make new datastores that follow my method.
Alternatively (although I believe this is less efficient) is to have all downloads in one huge table that can be loaded with one GetAsync, and saved with UpdateAsync. From this you can construct a page table.
Here’s two example functions I’ve made using an OrderedDatastore:
local dss = game:GetService("DataStoreService")
local myOrderedDataStore = dss:GetOrderedDataStore("FunnyOrderedDatastore !!!")
-- some simple functions that demonstrate the use of an OrderedDatastore
local function getPage(pageSize,ascendingOrder,min,max)
-- make sure invalid arguments are not passed
if typeof(ascendingOrder) ~= "boolean" then
ascendingOrder = false
end
if typeof(pageSize) ~= "number" then
pageSize = 10
end
local allPages = myOrderedDataStore:GetSortedAsync(ascendingOrder,pageSize,min,max) -- get the object for getting pages
local indexesOnPage = allPages:GetCurrentPage() -- get the current page
return indexesOnPage
end
local function getAllData()
local allPages = myOrderedDataStore:GetSortedAsync(false,100) -- get object for getting pages
local allData = {}
while true do
local page = allPages:GetCurrentPage() -- get the current page
for key,value in pairs(page) do
allData[key] = value
end
if allPages.IsFinished then -- if we're at the last page
break
end
page:AdvanceToNextPageAsync() -- go to the next page
end
return allData
end
print(getAllData())
-- can still be read and written to like a normal datastore
myOrderedDataStore:SetAsync("Build1", 55)
myOrderedDataStore:SetAsync("Build2", 32)
myOrderedDataStore:SetAsync("Build3", 68)
If I wanted to have the player press the next button and request a load for the next page, what would I do? Should I save the allpages instance in a table and then use advancetonextpageasync() when they request it?
i ended up making the script access the ordered datastore and whenever a page turn is called, store the current page in a cache for players who want to flip back a page later on