Creating a global leaderboard with a normal datastore

Hello Devforum, I need help creating a global leaderboard without the use of an ordered datastore.
I do not know if I should convert to an ordered datastore just for this as my game saves other things besides just leaderstats as well. What should I do from here?
Thanks.

2 Likes

One option is to calculate the leaderboard on demand. This means fetching all the necessary data from your normal datastore, sorting it based on the leaderboard criteria, and returning the results whenever a leaderboard request is made. While this method may be slower than using an ordered datastore, it eliminates the need for additional data storage. Another approach is to implement caching. You can store the leaderboard results temporarily in a cache and update it whenever a player’s stats change or when a new player joins. By serving leaderboard requests from the cache, you can reduce the frequency of calculations. However you’ll need to handle cache invalidation and updates accurately to keep the leaderboard up to date

Alternatively, you can create a separate data structure alongside your normal datastore. This structure can be optimized for leaderboard operations, such as a sorted list or a binary heap. Whenever a player’s stats change, you update this separate data structure accordingly. While this approach requires additional storage and maintenance, it can provide efficient leaderboard calculations without converting your entire datastore Xx :kiss:

3 Likes

I tried using ordered datastores and got very confused. I attempted to follow this tutorial here. https://devforum.roblox.com/t/how-to-make-a-simple-global-leaderboard/256754
I tried editing the script to fit what i need but it seems to have not worked. I am completely lost here and have no clue what to do as this is not erroring.

local sg = script.Parent
local sample = script:WaitForChild("Sample") --Our Sample frame
local sf = sg:WaitForChild("ScrollingFrame") --The scrolling frame
local ui = sf:WaitForChild("UI") --The UI list layout

local dataStoreService = game:GetService("DataStoreService")
--The data store service
local dataStore = dataStoreService:GetOrderedDataStore("SadRockLeaderboardData")
local mainData = dataStoreService:GetDataStore("GameData")
--Get the data store with key "Leaderboard"

wait(10)
while true do
	for i,plr in pairs(game.Players:GetChildren()) do--Loop through players
		if plr.UserId>0 then--Prevent errors
			local sdaroc = plr.leaderstats.SadRocks.Value --Get point balance
			if sdaroc then
				pcall(function()
					--Wrap in a pcall so if Roblox is down, it won't error and break.
					dataStore:UpdateAsync(plr.UserId,plr.leaderstats.SadRocks.Value)		--Set new value end)
				end)
			end
		end
	end    
	local smallestFirst = false--false = 2 before 1, true = 1 before 2
	local numberToShow = 100--Any number between 1-100, how many will be shown
	local minValue = 1--Any numbers lower than this will be excluded
	local maxValue = 10 --(10^30), any numbers higher than this will be excluded
	local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)
	--Get data
	local top = pages:GetCurrentPage()--Get the first page
	local data = {}--Store new data
	
	for a,b in ipairs(top) do--Loop through data
		local userid = b.key--User id
		local sadrocks = b.value--Points
		local username = "[Failed To Load]"--If it fails, we let them know
		local s,e = pcall(function()
			username = game.Players:GetNameFromUserIdAsync(userid)--Get username
		end)
		if not s then--Something went wrong
			warn("Error getting name for "..userid..". Error: "..e)
		end
		--Make a image of them
		table.insert(data,{username,sadrocks})--Put new data in new table
	end
	ui.Parent = script
	sf:ClearAllChildren()--Remove old frames
	ui.Parent = sf
	for number,d in pairs(data) do--Loop through our new data
		local name = d[1]
		local val = d[2]
		local color = Color3.new(1,1,1)--Default color
		if number == 1 then
			color = Color3.new(1,1,0)--1st place color
		elseif number == 2 then
			color = Color3.new(0.9,0.9,0.9)--2nd place color
		elseif number == 3 then
			color = Color3.fromRGB(166, 112, 0)--3rd place color
		end
		local new = sample:Clone()--Make a clone of the sample frame
		--new.Player = name--Set name for better recognition and debugging
		new.LayoutOrder = number--UIListLayout uses this to sort in the correct order
		new.Rank.Text = number--Set the place
		new.Rank.TextColor3 = color--Set the place color (Gold = 1st)
		new.Player.Text = name--Set the username
		new.amt.Text = val--Set the amount of points
		new.amt.TextColor3 = color--Set the place color (Gold = 1st)
		new.Player.TextColor3 = color--Set the place color (Gold = 1st)
		new.Parent = sf--Parent to scrolling frame
	end
	wait()
	sf.CanvasSize = UDim2.new(0,0,0,ui.AbsoluteContentSize.Y)
	--Give enough room for the frames to sit in
	wait(20)
end

(i did not understand how to link the two datastores either in order to get the “sadrocks” value.)
It is also not even going onto the leaderboard either.

There are a few issues and missing parts in the code that could be causing problems. You mentioned that you’re unsure how to link the two datastores to get the “SadRocks” value. To link the two datastores, you’ll need to fetch the player’s “SadRocks” value from the main datastore and update it in the ordered datastore X

1 Like

Thank you! I never worked with ordered datastores so I just read some of the documentation and just made the solution of getting the players leaderstat value whenever they are in game.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.