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.
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.