Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How do I create a sequenced ordered data store leaderboard?

Hello,

Recently, I have created a leaderboard script in ServerScriptService for my game. It controls creating a stage, cash and wins leaderboard, which works great using DataStore2 :)

I have had a couple of issues on a part of this leaderboard, the ordered data store part.

Firstly, it does not order the wins in a high to low order. It has sequenced the players in a 'last updated' order.

For example:

What my leaderboard is showing:

https://cdn.discordapp.com/attachments/356675974928007168/518192064706379787/unknown.png

What I'm trying to get it to show:

https://cdn.discordapp.com/attachments/356675974928007168/518192333758398535/example.png

Secondly, I am having issues where the leaderboard doesn't appear at all. But then other times it appears. I think it is because ROBLOX has troubles with data stores ATM. That's why I switched to DataStore2 on standard data stores. If that is the answer to the problem, how do I use my ordered data store on the DataStore2 system?

This is an example on the leaderboard not appearing:

https://cdn.discordapp.com/attachments/356675974928007168/518193965791576092/unknown.png

This is the DataStore2 module and system:

Module: https://www.roblox.com/library/1936396537/DataStore2-Data-Loss-Prevention-and-Caching

Description: https://devforum.roblox.com/t/how-to-use-datastore2-data-store-caching-and-data-loss-prevention/136317

This is my current code for the leaderboard script in ServerScriptStorage:

The parts of the code that is relevant to the ordered data store leaderboard are lines 1-52.

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
local ODS = game:GetService("DataStoreService"):GetOrderedDataStore("WinsFixed")
local Pages = ODS:GetSortedAsync(false,10)
local Data = Pages:GetCurrentPage()
local GUI1=game.StarterGui.LeaderboardUI
local GUI2=game.StarterGui.LeaderboardUI1

local function Update()
	local succ,err = pcall(function()
		local Template = GUI1.Template
			for i,v in pairs(GUI1.MainFrame:GetChildren()) do
				if v:IsA("Frame") then
					v:Destroy()
				end
			end
		local Template2 = GUI2.Template
			for i,v in pairs(GUI2.MainFrame:GetChildren()) do
				if v:IsA("Frame") then
					v:Destroy()
				end
			end
		for a,k in pairs(Data) do
			local PlayerName = k.key
			local PlayerPoints = k.value
			local NewTemp = Template:Clone()
			NewTemp.Name = PlayerName
			NewTemp.FrameName.Text = PlayerName
			NewTemp.FrameValue.Text = PlayerPoints
			NewTemp.Visible = true
			NewTemp.Parent = GUI1.MainFrame
			NewTemp:Clone().Parent = GUI2.MainFrame
		end
	end)
	if err then
		warn("An error has occurred when trying to update leaderboard: " .. err)
		Update()
	end
end

game.Workspace.ChildAdded:Connect(function(object)
	local player = game.Players:GetPlayerFromCharacter(object)
	if player ~= nil then
		local ls = player:WaitForChild("leaderstats")
		local sl = game.Workspace:FindFirstChild(ls.Stage.Value)
		object.UpperTorso.CFrame = object.UpperTorso.CFrame + Vector3.new(0,3,0)
		wait()
		object.UpperTorso.CFrame = sl.CFrame + Vector3.new(0,3,0)
		while wait(60*3) do
			Update()
		end
	end
end)

game.Players.PlayerAdded:Connect(function(player)
	
	local cashDataStore = DataStore2("cash",player)
	local deathsDataStore = DataStore2("deaths",player)
	local standardDataStore = DataStore2("standard",player)
	local perfectDataStore = DataStore2("perfect",player)
	local speedDataStore = DataStore2("speed",player)
	
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"
	
	local winstats = Instance.new("Folder",player)
	winstats.Name = "winstats"
	
	local stage = Instance.new("IntValue",leaderstats)
	stage.Name = "Stage"
	stage.Value = 1
	
	local cash = Instance.new("IntValue",leaderstats)
	cash.Name = "Cash"
	
	local deaths = Instance.new("IntValue",winstats)
	deaths.Name = "Deaths"
	
	local BestPerfect = Instance.new("IntValue",winstats)
	BestPerfect.Name = "BestPerfect"

	local BestStandard = Instance.new("IntValue",winstats)
	BestStandard.Name = "BestStandard"

	local BestSpeed = Instance.new("IntValue",winstats)
	BestSpeed.Name = "BestSpeed"
	
	local specialmode = Instance.new("BoolValue",winstats)
	specialmode.Name = "Special"
	
	local mode = Instance.new("StringValue",leaderstats)
	mode.Name = "Mode"
	mode.Value = "Standard"
	
	local perfectmode = Instance.new("BoolValue",winstats)
	perfectmode.Name = "Perfect"

	local speedmode = Instance.new("BoolValue",winstats)
	speedmode.Name = "Speed"

	local Wins = Instance.new("NumberValue",winstats)
	Wins.Name = "Wins"
	
	local function cashUpdate(updatedValue)
		cash.Value = cashDataStore:Get(updatedValue)
	end
	
	local function deathsUpdate(updatedValue)
		deaths.Value = deathsDataStore:Get(updatedValue)
	end
	
	local function BestStandardUpdate(updatedValue)
		BestStandard.Value = standardDataStore:Get(updatedValue)
	end
	
	local function BestPerfectUpdate(updatedValue)
		BestPerfect.Value = perfectDataStore:Get(updatedValue)
	end
	
	local function BestSpeedUpdate(updatedValue)
		BestSpeed.Value = speedDataStore:Get(updatedValue)
	end
	
	cashUpdate(0)
	cashDataStore:OnUpdate(cashUpdate)
	
	deathsUpdate(0)
	deathsDataStore:OnUpdate(deathsUpdate)
	
	BestStandardUpdate(0)
	standardDataStore:OnUpdate(BestStandardUpdate)

	BestPerfectUpdate(0)
	perfectDataStore:OnUpdate(BestPerfectUpdate)

	BestSpeedUpdate(0)
	speedDataStore:OnUpdate(BestSpeedUpdate)
	
	player.CharacterAdded:Connect(function(Character)
		local d = true
		Character:WaitForChild("Humanoid").Died:Connect(function()
			if (d) then
				d = false
				local deathsDataStore = DataStore2("deaths",player)
				deathsDataStore:Increment(1, 0)
			end
		end)
	end)
	
	while true do
		wait()
		if (player.winstats.BestPerfect.Value == 11) and (player.leaderstats.Stage.Value > player.winstats.BestSpeed.Value) then
			if player.winstats.Perfect.Value ~= true then
				local speedDataStore = DataStore2("speed",player)
				speedDataStore:Set(player.leaderstats.Stage.Value)
			end
			
		elseif (player.winstats.BestStandard.Value == 11) and (player.leaderstats.Stage.Value > player.winstats.BestPerfect.Value) then
			local perfectDataStore = DataStore2("perfect",player)
			perfectDataStore:Set(player.leaderstats.Stage.Value)
		
		elseif player.leaderstats.Stage.Value > player.winstats.BestStandard.Value then
			local standardDataStore = DataStore2("standard",player)
			standardDataStore:Set(player.leaderstats.Stage.Value)
		
		end
		
		wait(40)
		local cashDataStore = DataStore2("cash",player)
		cashDataStore:Increment(1, 0)
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local Wins = plr.winstats.Wins
	if Wins then
		ODS:IncrementAsync(plr.Name, Wins.Value)
	end
end)

Any advice you can give will be appricated.

1 answer

Hello,

I have asked a couple of roblox scripting pros about this. They said this: First of all, they don't think ordered data stores are compatible with DataStore2.

Secondly, the reason why the leaderboard doesn't appear all the time is that the script is needed to include a new pcall function. As shown in the script.

Thirdly, the reason why the leaderboard isn't displaying in the correct order is that the UiListLayout of the actual UI has been setup incorrectly. These are the correct settings for my leaderboard:

https://cdn.discordapp.com/attachments/356675974928007168/524317164220579843/unknown.png

Another reason why the leaderboard didn't display in the correct order, is that I needed to include a new line of code which ordered the leaderboard, as it updated. Here is the corrected version of the code:

local DataStore2 = require(game.ServerScriptService:WaitForChild("MainModule"))
local ODS = game:GetService("DataStoreService"):GetOrderedDataStore("WinsFixed")
local GUI1=game.StarterGui.LeaderboardUI
local GUI2=game.StarterGui.LeaderboardUI1

local function load()
	local succ,err = pcall(function()            --New pcall function
        warn("Successfully loaded the leaderboard")
		local Pages = ODS:GetSortedAsync(true,10)
		local Data = Pages:GetCurrentPage()
		local Template = GUI1.Template
		
		for i,v in pairs(GUI1.MainFrame:GetChildren()) do
			if v:IsA("Frame") then
				v:Destroy()
			end
		end
		local Template2 = GUI2.Template
		for i,v in pairs(GUI2.MainFrame:GetChildren()) do
			if v:IsA("Frame") then
				v:Destroy()
			end
		end
		local succ2,err2 = pcall(function()
			for a,k in pairs(Data) do
				local PlayerName = k.key
				local PlayerPoints = k.value
				local NewTemp = Template:Clone()
				NewTemp.Name = PlayerName
                NewTemp.LayoutOrder = 10-a    --New line
				NewTemp.FrameName.Text = PlayerName
				NewTemp.FrameValue.Text = PlayerPoints
				NewTemp.Visible = true
				NewTemp.Parent = GUI1.MainFrame
				NewTemp:Clone().Parent = GUI2.MainFrame
			end
		end)
		if err2 then
			warn("No data to process")
			return
		end
	end)
	if err then
		warn("Failed to load the leaderboard")
		load()
	end
end

I have got rid of the 'Update' function and joined the two functions together for simplicity. Hope this helps.

1 comment

0

Thanks for replying to yourself, I am now finding this useful.

This discussion is preserved as it was. New answers, comments, and votes are closed.