How to make Global Leaderboard using DataStore2?

Hello!
So, I started using DataStore2 (Post: How to use DataStore2 - Data Store caching and data loss prevention)
I want to make global leaderboard with rebirths and time spent in the game.
Everything works fine (DataStore2), but I don’t know, how would I make global leaderboard with ordered datastore.
I was watching a YT tutorial about it and some code, but I didn’t get it to work (which is obvious). So, basically. Is there any way to do it? I really want to have global leaderboard and keep DataStore2.

Here’s the script, I have right now:

local DataStore2 = require(game.ServerScriptService.DataStore2)

for i = 1, 10 do
	local Sam = script.Sample:Clone()
	Sam.Name = i
	Sam.Parent = script.Parent.Frame.Leaderboard
	Sam.UserPos.Text = tostring(i)
	Sam.score.Text = "nil"
	Sam.UserName.Text = ""
	Sam.LayoutOrder = i
end

function updateGui()
	for i,v in pairs(game.Players:GetChildren()) do
		local DataStoreTimegame:GetService("DataStoreService"):GetOrderedDataStore("TimeLeaderboard")
		local timeData = DataStore2("Time", v)
		local Data = 1
		DataStoreTime:SetAsync(v.UserId,Data)
	end
	local DataStore = game:GetService("DataStoreService"):GetOrderedDataStore("TimeLeaderboard")
	local Pages = DataStore:GetSortedAsync(false,10)
	local Data = Pages:GetCurrentPage()
	for k,v in pairs(Data) do
		if tonumber(v.key) >= 1 then
			local frame = script.Parent.Frame.Leaderboard:FindFirstChild(tostring(k))
			if frame then
				frame.UserName.Text = game.Players:GetUserIdFromNameAsync(v.key)
				frame.score.Text = tostring(v.Value)
			end
		end
	end
end

while true do
	updateGui()
	wait(2)
end

Thank you!

1 Like

Hey!
So the issue with your predicament, is that DataStore2’s don’t support OrderedDatastores (to my knowledge). This means that you can’t use that module for that particular purpose.

However, if you don’t mind Data Redundancy, you can potentially store the data under an OrderedDatastore and you can craft together a solution that additionally updates that OrderedDatastore whenever DataStore2 is asked to update something. There are probably plenty of better solutions to this, so feel free to check out his API for some more info.

1 Like

I did it. I kept my Datastore2 and made global leaderboards. I didn’t make a leaderstats, so I just save all the values in a folder called “Saves” in Player that Datastore2 saved and have SetAync use the values from there. I have like 35 values to save, so I like Datastore2 to keep them clean and organized.

The script below is the serverscript in ServerScriptService for the Total Blocks mined leaderboard surfacegui. I duplicate the script and find/replace all “totalblocks” for the next corresponding global leaderboard.

local totalblocksODS = 
game:GetService("DataStoreService"):GetOrderedDataStore("totalblocksODS")


local function Handler()
	local Success, Err = pcall(function()
		local Data = totalblocksODS:GetSortedAsync(false, 5)
		local amountsPage = Data:GetCurrentPage()
		for Rank, Data in ipairs(amountsPage) do
			local Name = Data.key
			local totalblocks = Data.value
			local NewObj = game.ReplicatedStorage:WaitForChild("lbFrametotalblocks"):Clone()
			NewObj.Player.Text = Name
			local SuffixList = {"", "K", "M", "B", "T", "Qd", "Qn", "Sx", "Sp", "Oc", "No", "De", "UDe", "DDe", "TDe", "QdDe","QnDe", "SxDe", "SpDe", "OcDe", "NoDe", "Vt", "UVt", "DVt", "TVt", "QdVt", "QnVt", "SxVt", "SpVt", "OcVt", "NoVt", "Tg", "UTg", "DTg", "TTg", "QdTg", "QnTg", "SxTg", "SpTg", "OcTg", "NoTg", "qg", "Uqg", "Dqg", "Tqg", "Qdqg", "Qnqg", "Ocqg", "Noqg", "Qg", "UQg", "DQg", "TQg", "QdQg", "QnQg", "SxQg", "SpQg", "OcQg", "NoQg", "sg", "Usg", "Dsg", "Tsg", "Qdsg", "Qnsg", "Sxsg", "Spsg", "Ocsg", "Nosg", "Sg", "USg", "DSg", "TSg", "QdSg", "QnSg", "SxSg", "SpSg", "OcSg", "NoSg", "Og", "UOg", "DOg", "TOg", "QdOg", "QnOg", "SxOg", "SpOg", "OcOg", "NoOg", "Ng", "UNg", "DNg", "TNg", "QdNg", "QnNg", "SxNg", "SpNg", "OcNg", "NoNg", "Ce", "UCe"}

			local function Format(value, idp)
				local exp = math.floor(math.log(math.max(1, math.abs(value)), 1000))
				local suffix = SuffixList[1 + exp] or ("e+" .. exp)
				local norm = math.floor(value *((10 ^ idp) / (1000 ^ exp))) / (10 ^ idp)


				return("%.".. idp .. "f%s"):format(norm, suffix)
			end	
			NewObj.totalblocks.Text = Format(totalblocks,1)
			NewObj.Rank.Text = "#"..Rank
			NewObj.Position = UDim2.new(0, 0, NewObj.Position.Y.Scale + (0.08 * #workspace.Globaltotalblocks.lbGUI.Holder:GetChildren()), 0)
			NewObj.Parent = workspace.Globaltotalblocks.lbGUI.Holder
		end
	end)
	if not Success then
		error(Err)
	end
end

while true do
	for _,Player in pairs(game.Players:GetPlayers()) do
		totalblocksODS:SetAsync(Player.Name, Player.Saves.totalblocks.Value)
	end
	for _,v in pairs(workspace.Globaltotalblocks.lbGUI.Holder:GetChildren()) do
		if v.Name == "lbFrametotalblocks" then
			v:Destroy()
		end
	end
	Handler()
	wait(300)
end