Lojas de dados são um serviço que você pode usar para salvar e carregar dados persistentes de jogadores em diferentes sessões de jogador. Elas armazenam informações importantes, como o progresso ou inventário de um jogador, e permitem que você as recupere para o jogador na próxima vez que ele entrar no seu jogo. Sem lojas de dados, um jogador perderia todo o seu progresso toda vez que saísse do jogo.
Existem dois tipos de lojas de dados: padrão e ordenadas. Este tutorial usa lojas de dados ordenadas, que armazenam dados que você pode classificar e ordenar numericamente e recuperar em ordem crescente ou decrescente com base nos valores numéricos armazenados.
Usando o arquivo do tutorial de tabela de classificação Gold Rush - Início .rbxl como ponto de partida e o arquivo do tutorial de tabela de classificação Gold Rush - Completo .rbxl como referência, este tutorial fornece a você a base necessária para criar uma tabela de classificação personalizada de jogadores, incluindo orientações sobre:
- Armazenar pontuações de ouro em uma loja de dados ordenada.
- Buscar e classificar as melhores pontuações globalmente em todos os servidores.
- Exibir as melhores pontuações em uma tabela de classificação personalizada na IU.
- Atualizar automaticamente a tabela de classificação personalizada a cada poucos segundos.
Ao final deste tutorial, você deve ter o seguinte:
- Sob ServerScriptService:
- Um script GoldManager atualizado que salva a pontuação do jogador em uma loja de dados ordenada para a tabela de classificação.
- Um novo script de módulo LeaderboardRemoteHandler que busca e retorna a lista classificada das melhores pontuações da tabela de classificação.
- Um novo script LeaderboardManager que responde aos pedidos de dados da tabela de classificação do cliente, atuando como uma ponte entre o cliente no LeaderboardGuiScript e o servidor no LeaderboardManager.
- Sob StarterGui, um novo script local LeaderboardGuiScript que renderiza a IU da tabela de classificação para o jogador.

Habilitar acesso do Studio aos serviços da API
As lojas de dados não são armazenadas localmente no seu dispositivo, então seu jogo depende da comunicação servidor a servidor com o backend da Roblox para utilizá-las. Por padrão, o Studio restringe essa comunicação para evitar abusos ou uso acidental. O acesso aos serviços da API no Studio está desativado até que você o habilite explicitamente para garantir que apenas jogos confiáveis possam ler e escrever nos servidores de backend da Roblox.
Para habilitar o acesso do Studio aos serviços da API para que você possa usar lojas de dados:
- Abra o arquivo tutorial de tabela de classificação Gold Rush - Início no Studio. Este arquivo de ponto de partida já inclui o código do tutorial Salvar dados do jogador e a estrutura da IU para a tabela de classificação do jogador.
- De volta ao Studio, vá para Arquivo ⟩ Configurações da Experiência ⟩ Segurança.
- Ative Habilitar acesso do Studio aos serviços da API.
- Salve suas alterações.
Criar uma loja de dados ordenada
Ao criar uma loja de dados, você deve sempre chamar o DataStoreService a partir de um Script do lado do servidor. Isso é importante porque:
- A Roblox bloqueia todo acesso à loja de dados do cliente para que apenas o servidor tenha permissão para acessar e modificar dados persistentes de jogadores.
- Scripts do lado do servidor são executados em um ambiente centralizado, garantindo que os dados sendo lidos e escritos para a sua loja de dados sejam precisos e válidos.
- Como os scripts do lado do cliente são executados no dispositivo do jogador, qualquer jogador poderia potencialmente explorar o jogo e roubar ou sobrescrever os dados de outros jogadores se o cliente tivesse acesso às suas lojas de dados.
Você também deve dar à sua loja de dados um nome único para manter seus dados organizados e para evitar que se sobreponham ou entrem em conflito em diferentes lojas de dados. Neste tutorial, a loja de dados para a tabela de classificação é chamada de GlobalLeaderboard.
Para criar a loja de dados ordenada GlobalLeaderboard:
Abra o script GoldManager existente em ServerScriptService.

Sob a loja de dados PlayerGold existente, chame GetOrderedDataStore com a string "GlobalLeaderboard". Isso cria uma loja de dados ordenada para salvar a pontuação do jogador quando ele ganha ouro.
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
Após criar uma loja de dados, você pode referenciar essa mesma loja de dados em diferentes scripts. Por exemplo, você pode chamar GetOrderedDataStore tanto no script GoldManager quanto no script de módulo LeaderboardManager que você criará mais tarde neste tutorial. Referenciar a mesma loja de dados em dois lugares não significa que você está duplicando dados; isso apenas significa que dois scripts estão acessando o mesmo armazenamento centralizado, como dois colegas de equipe usando uma pasta para compartilhar informações.
Enviar dados do jogador para a tabela de classificação
As lojas de dados são compostas por chaves, que identificam dados, e valores, que armazenam dados. Ao contrário das lojas de dados padrão, as lojas de dados ordenadas permitem que você classifique dados por valor, o que as torna ideais para criar coisas como tabelas de classificação.
Cada entrada em uma loja de dados ordenada é armazenada sob uma chave única que você pode classificar e ordenar numericamente e, em seguida, recuperar em ordem crescente ou decrescente com base nos valores numéricos armazenados. Isso significa que você pode usar lojas de dados ordenadas para, por exemplo, mostrar uma lista das 3 melhores que se atualiza em tempo real à medida que jogadores em seu jogo coletam mais ouro.
| Chave | Valor | |
|---|---|---|
| Descrição | Uma chave é um identificador de string único que você pode usar para acessar uma peça específica de dados, como o ID do usuário de um jogador. As chaves permitem que você organize seus dados para gerenciá-los e depurá-los facilmente. | Um valor é o dado numérico real que você deseja salvar ou carregar, como a pontuação de um jogador. Os valores permitem que você armazene o progresso entre sessões, assim como recuperar dados do jogador na próxima vez que ele entrar no seu jogo. |
| Formatos permitidos | Podem ser apenas strings. Se você estiver usando números, como um ID de usuário, converta-os em uma string usando tostring(). | Podem ser apenas números. |
| Exemplos | "Player_A", "TopScore", "123456" (ID do usuário como string) | 100, 3.14, 0, -25 |
Agora que você criou sua loja de dados ordenada GlobalLeaderboard, atualize a função saveGold existente no script GoldManager para enviar a pontuação de ouro do jogador para sua tabela de classificação personalizada com SetAsync:
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("Não foi possível salvar o ouro de", player.Name, ":", err)
end
end
Você pode pensar na loja de dados ordenada GlobalLeaderboard como uma pasta compartilhada: SetAsync adiciona conteúdo à pasta, enquanto GetSortedAsync (que você criará mais tarde no script de módulo LeaderboardManager) lê o conteúdo da pasta e o classifica por pontuação.
Buscar as pontuações da tabela de classificação
Para buscar as pontuações da tabela de classificação, você deve usar um ModuleScript. Scripts de módulo permitem que você organize e reutilize seu código em vários scripts. Em vez de copiar a mesma lógica em lugares diferentes, você pode escrevê-la uma vez em um script de módulo e chamá-la de qualquer lugar que precise.
Quando você armazena sua lógica de tabela de classificação em um módulo, tanto o manipulador da IU quanto os scripts do servidor podem usar a mesma função para buscar as melhores pontuações dos jogadores. Se você precisar, por exemplo, atualizar como os nomes de usuários são buscados ou como as pontuações são classificadas, você só precisará alterar o código em um lugar. Após atualizar o módulo, todos os scripts que o utilizam também receberão automaticamente o comportamento atualizado.
Sua tabela de classificação personalizada usa os seguintes métodos da loja de dados ordenada para compartilhar dados entre diferentes servidores:
- SetAsync (do script GoldManager) para enviar as pontuações dos jogadores para a loja de dados ordenada GlobalLeaderboard.
- GetSortedAsync (no script de módulo) para buscar as melhores pontuações de todos os servidores a partir da mesma loja de dados. O método GetSortedAsync é exclusivo para lojas de dados ordenadas e pode recuperar várias chaves ordenadas com base em uma ordem específica de classificação, tamanho da página e valores mínimos e máximos.
Para buscar as pontuações da tabela de classificação:
Sob ServerScriptService, crie um novo ModuleScript chamado LeaderboardManager.
No topo do script do módulo, chame GetOrderedDataStore com a string "GlobalLeaderboard". Referenciar a mesma loja de dados ordenada que você criou no script GoldManager permitirá que a IU da tabela de classificação busque e classifique as melhores pontuações dos jogadores posteriormente.
local DataStoreService = game:GetService("DataStoreService")local Players = game:GetService("Players")local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")Prepare uma tabela de módulo para armazenar todas as funções e dados que você deseja expor para outros scripts.
local leaderboardManager = {}Crie uma função chamada GetTopScores para obter as melhores pontuações dos jogadores. Esta função:
- Chama GetSortedAsync para buscar o número limit de melhores pontuações em ordem decrescente. Se a chamada falhar, uma lista vazia é retornada para evitar que o restante do seu código falhe.
- Loop através da tabela da tabela de classificação para obter uma tabela de entradas com GetCurrentPage e nomes de usuários com GetNameFromUserIdAsync.
- Adiciona cada resultado a uma lista final e constrói uma tabela de classificação com nomes de usuários dos jogadores e suas pontuações.
- Retorna a lista final de jogadores e envia os dados da tabela de classificação de volta a qualquer script que chamar esta função leaderboardManager.GetTopScores.
function leaderboardManager.GetTopScores(limit)local success, pages = pcall(function()return leaderboardStore:GetSortedAsync(false, limit)end)if not success or not pages thenreturn {}endlocal results = {}for _, entry in ipairs(pages:GetCurrentPage()) dolocal userId = tonumber(entry.key)local score = entry.valuelocal username = "Desconhecido"local ok, name = pcall(function()return Players:GetNameFromUserIdAsync(userId)end)if ok thenusername = nameendtable.insert(results, {Username = username,Score = score})endreturn resultsendTorne o módulo utilizável retornando a tabela do módulo que você criou anteriormente. Sempre que você criar um script de módulo, deve retornar a tabela do módulo para que outros scripts possam acessá-la e chamar as funções dentro dela.
return leaderboardManager
Solicitar dados da tabela de classificação do servidor
Para que a IU do cliente exiba as pontuações da tabela de classificação, o servidor deve responder quando o cliente solicitar dados. Um RemoteFunction permite que o cliente solicite informações do servidor e aguarde uma resposta.
Para solicitar dados da tabela de classificação do servidor:
Sob ReplicatedStorage, insira uma RemoteFunction chamada LeaderboardRemote. Esta função remota atua como a ponte entre o script da IU no cliente e a lógica da tabela de classificação no servidor.
Sob ServerScriptService, crie um script chamado LeaderboardRemoteHandler. Neste script:
Chame ReplicatedStorage (o espaço compartilhado entre cliente e servidor), ServerScriptService (que contém o módulo de tabela de classificação) e leaderboardRemote (a função remota que o cliente chamará para pedir os dados da tabela de classificação).
local ReplicatedStorage = game:GetService("ReplicatedStorage")local ServerScriptService = game:GetService("ServerScriptService")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Carregue o módulo LeaderboardManager que você criou anteriormente, que inclui a função que obtém as melhores pontuações da loja de dados ordenada.
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))Defina o comportamento para quando o cliente chamar InvokeServer. O servidor responde buscando as 3 melhores pontuações e enviando o resultado de volta ao cliente.
leaderboardRemote.OnServerInvoke = function(player)return leaderboardManager.GetTopScores(3)end
Exibir dados na IU personalizada da tabela de classificação
Depois de configurar os scripts do lado do servidor, crie um script local para buscar os 3 melhores jogadores a cada 3 segundos e exibir os resultados em uma tabela de classificação global na IU dentro do jogo.
Para exibir dados na sua tabela de classificação personalizada:
Sob StarterGui ⟩ LeaderboardGui, crie um script local chamado LeaderboardGuiScript.
No topo do script, conecte-se à função remota. Chame ReplicatedStorage para obter acesso a objetos compartilhados entre o servidor e o cliente, e depois chame leaderboardRemote para permitir que o cliente solicite os dados da tabela de classificação do servidor.
local ReplicatedStorage = game:GetService("ReplicatedStorage")local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")Referencie os elementos existentes da IU da tabela de classificação sob LeaderboardGui.
local gui = script.Parentlocal leaderboardFrame = gui:WaitForChild("LeaderboardFrame")local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame")local template = entriesFrame:WaitForChild("LeaderboardEntry")Crie uma função chamada clearEntries para limpar entradas antigas da tabela de classificação. Esta função percorre todos os filhos de entriesFrame, que contém as linhas da tabela de classificação, e garante que a tabela seja totalmente atualizada antes de exibir novos dados.
local function clearEntries()for _, child in ipairs(entriesFrame:GetChildren()) doif child:IsA("TextLabel") and child.Name:match("^Row%d+$") thenchild:Destroy()endendendCrie uma função chamada renderLeaderboard para inserir e exibir dados dos jogadores nas linhas da tabela de classificação. O objeto data é uma tabela retornada pelo servidor que contém entradas com os nomes de usuários dos jogadores e pontuações.
local function renderLeaderboard(data)clearEntries()for i, entry in ipairs(data) dolocal row = template:Clone()row.Name = "Row" .. irow.Visible = truerow.LayoutOrder = irow.Text = string.format("%d%s lugar: %s - %d",i, i == 1 and "º" or i == 2 and "º" or i == 3 and "º" or "º",entry.Username, entry.Score)row.Parent = entriesFrameendendCrie um loop para buscar periodicamente os dados da tabela de classificação. A cada 3 segundos, o loop executa e chama o servidor usando a função InvokeServer que você criou anteriormente no script LeaderboardRemoteHandler. Se a chamada for bem-sucedida, a IU é atualizada com as pontuações atualizadas.
while true dolocal success, data = pcall(function()return leaderboardRemote:InvokeServer()end)if success and data thenrenderLeaderboard(data)endtask.wait(3)end
Código final
Veja os seguintes trechos de código para os scripts completos GoldManager, LeaderboardManager, LeaderboardRemoteHandler e LeaderboardGuiScript. Você pode copiá-los e executá-los diretamente no arquivo do tutorial de tabela de classificação Gold Rush - Início .rbxl no Studio.
GoldManager
O script GoldManager cria uma loja de dados ordenada para gerenciar as atualizações da tabela de classificação.
-- Obter serviços
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local DataStoreService = game:GetService("DataStoreService")
-- Evento remoto para atualizar a IU
local uiEvent = ReplicatedStorage:WaitForChild("UIEvent")
-- Loja de dados para salvar os pedaços de ouro do jogador
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Loja de dados ordenada para salvar ouro na tabela de classificação
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Criar um gerador de números aleatórios para posicionar pedaços de ouro
local random = Random.new()
-- Tabela para armazenar os pedaços de ouro do jogador para uma única sessão
local playerGold = {}
-- Constantes
local GOLD_VALUE = 10 -- Quanto cada pedaço de ouro vale
local GOLD_REGENERATION_BOUNDS = { -- Limites da área usados para reposicionar pedaços de ouro aleatoriamente
minX = -72,
maxX = 72,
minZ = -72,
maxZ = 72
}
local GOLD_REGEN_DELAY = 2 -- O atraso antes que um pedaço reapareça (em segundos)
local AUTOSAVE_INTERVAL = 30 -- Com que frequência os pedaços do jogador são salvos (em segundos)
-- Função para lidar com o toque do jogador em um pedaço de ouro
local function processGoldTouch(chunk, player)
-- Ocultar o pedaço quando o jogador o coletar
chunk.Parent = nil
-- Adicionar o pedaço à pontuação de ouro do jogador na sessão
local userId = player.UserId
playerGold[userId] = (playerGold[userId] or 0) + GOLD_VALUE
print(player.Name, "agora tem", playerGold[userId], "ouro")
-- Atualizar a barra de pontuação da IU para refletir a nova pontuação de ouro desta sessão
uiEvent:FireClient(player, {
gold = playerGold[userId],
doTween = true,
showAlert = false
})
-- Esperar um pouco e depois reaparecer o pedaço de ouro que foi coletado em uma nova localização aleatória
task.delay(GOLD_REGEN_DELAY, function()
-- Reaparecer o pedaço de ouro em uma nova posição aleatória
local nextPositionX = random:NextInteger(GOLD_REGENERATION_BOUNDS.minX, GOLD_REGENERATION_BOUNDS.maxX)
local nextPositionZ = random:NextInteger(GOLD_REGENERATION_BOUNDS.minZ, GOLD_REGENERATION_BOUNDS.maxZ)
chunk.CFrame = CFrame.new(nextPositionX, 50, nextPositionZ) -- Mover o pedaço para a nova posição
chunk:SetAttribute("DropCollided", false) -- Redefinir quaisquer flags de colisão
chunk.Parent = workspace.GoldChunks
end)
end
-- Loop através de todas as partes marcadas como "Gold" e conectá-las à detecção de toque
for _, chunk in ipairs(CollectionService:GetTagged("Gold")) do
chunk.Touched:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
processGoldTouch(chunk, player)
end
end)
end
-- Função para salvar o ouro do jogador tanto nas lojas de dados padrão quanto nas ordenadas
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("Não foi possível salvar o ouro de", player.Name, ":", err)
end
end
-- Função para lidar com o jogador entrando no jogo
local function onPlayerAdded(player)
local userId = player.UserId
print(player.Name, "entrou no jogo")
-- Tentar carregar o ouro do jogador da loja de dados
local success, storedGold = pcall(function()
return goldStore:GetAsync(userId)
end)
-- Definir a pontuação de ouro da sessão atual usando o valor da loja de dados para o jogador
local currentGold = if success and storedGold then storedGold else 0
playerGold[userId] = currentGold
-- Atualizar a IU com o valor da loja de dados para o jogador
uiEvent:FireClient(player, {
gold = currentGold,
doTween = false,
showAlert = not success
})
if success then
print("Carregado", currentGold, "ouro para", player.Name)
else
-- Notificar o jogador de que seu ouro não pôde ser carregado
uiEvent:FireClient(player, { showAlert = true })
warn("Não foi possível carregar o ouro de", player.Name)
end
-- Iniciar a corrotina de salvamento automático para salvar o ouro do jogador a cada 30 segundos
coroutine.wrap(function()
while player.Parent do
task.wait(AUTOSAVE_INTERVAL)
if playerGold[userId] then
saveGold(player, playerGold[userId])
print("Salvando automaticamente", playerGold[userId], "ouro para", player.Name)
end
end
end)()
end
-- Função para lidar com o jogador saindo do jogo
local function onPlayerRemoving(player)
local userId = player.UserId
print(player.Name, "saiu do jogo")
-- Verificar se o ouro do jogador foi rastreado
if playerGold[userId] then
-- Salvar o ouro do jogador na loja de dados antes de ele sair
saveGold(player, playerGold[userId])
end
end
-- Conectar os eventos de entrada e saída do jogador
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)
LeaderboardManager
O script de módulo LeaderboardManager:
- Chama GetSortedAsync() na loja de dados ordenada GlobalLeaderboard.
- Converte IDs de usuários em nomes de usuários usando GetNameFromUserIdAsync.
- Retorna uma lista de tabelas { Username, Score } para os jogadores de melhor classificação.
- É chamado pelo LeaderboardRemoteHandler sempre que um cliente solicita dados da tabela de classificação.
-- Obter serviços
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- Loja de dados ordenada para salvar pontuações da tabela de classificação
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- Tabela para armazenar as pontuações da tabela de classificação
local leaderboardManager = {}
-- Função para retornar as melhores pontuações
function leaderboardManager.GetTopScores(limit)
-- Tentar recuperar uma página classificada de entradas da tabela de classificação da loja de dados
local success, pages = pcall(function()
-- false = decrescente (maiores pontuações primeiro)
return leaderboardStore:GetSortedAsync(false, limit)
end)
-- Se a chamada falhar ou não retornar nada, registre um aviso e retorne uma tabela vazia
if not success or not pages then
warn("Falha ao obter dados da tabela de classificação")
return {}
end
-- Criar uma tabela para armazenar os dados dos jogadores de melhor classificação
local topPlayers = {}
-- Loop através de cada entrada na página atual dos resultados da tabela de classificação
for _, entry in ipairs(pages:GetCurrentPage()) do
local userId = tonumber(entry.key) -- Converter a chave da entrada para um número (ID do usuário armazenado como string)
local score = entry.value -- O valor é a pontuação do jogador (quantidade de ouro)
local username = "Desconhecido" -- Um nome padrão caso a busca falhe
-- Tentar obter o nome do jogador a partir de seu ID de usuário
local ok, name = pcall(function()
return Players:GetNameFromUserIdAsync(userId)
end)
-- Se a busca for bem-sucedida, armazene o nome real do usuário
if ok then
username = name
end
-- Adicione esse jogador e sua pontuação à lista
table.insert(topPlayers, {
Username = username,
Score = score
})
end
-- Retorne a lista completa de jogadores de melhor classificação com seus nomes de usuário e pontuações
return topPlayers
end
-- Retorne o módulo LeaderboardManager para que outros scripts possam usá-lo
return leaderboardManager
LeaderboardRemoteHandler
O script LeaderboardRemoteHandler busca e retorna as 3 melhores pontuações para o cliente que chamou.
-- Obter serviços
local ServerScriptService = game:GetService("ServerScriptService") -- Acessar módulos do lado do servidor
local ReplicatedStorage = game:GetService("ReplicatedStorage") -- Objetos de comunicação compartilhada entre cliente e servidor
-- Aguardar a RemoteFunction que o cliente usa para solicitar dados da tabela de classificação
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Carregar o módulo LeaderboardManager que contém a função GetTopScores
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))
-- Configurar um manipulador para quando o cliente invocar a RemoteFunction da tabela de classificação
leaderboardRemote.OnServerInvoke = function(player)
-- Chamar o módulo da tabela de classificação para obter as 3 melhores pontuações e retorná-las ao cliente
return leaderboardManager.GetTopScores(3)
end
LeaderboardGuiScript
O script local LeaderboardGuiScript:
- Solicita dados da tabela de classificação ao servidor a cada 3 segundos usando Class.RemoteHandler.InvokeServer|InvokeServer.
- Usa um modelo oculto LeaderboardEntry para exibir cada linha da tabela de classificação.
- Formata cada linha como "1º lugar: Nome de Usuário - Pontuação".
- Gerencia a criação, exibição e layout das linhas da tabela de classificação usando UIListLayout.
-- Obter armazenamento compartilhado para acesso à RemoteFunction
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter a RemoteFunction usada para solicitar dados da tabela de classificação do servidor
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- Referências da IU
local gui = script.Parent -- O LocalScript sob o ScreenGui
local leaderboardFrame = gui:WaitForChild("LeaderboardFrame") -- Container principal para a tabela de classificação
local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame") -- Quadro onde as entradas da tabela de classificação aparecem
local template = entriesFrame:WaitForChild("LeaderboardEntry") -- Label de texto oculta usada para criar linhas
-- Função para remover antigas linhas da tabela de classificação (mas não o template)
local function clearEntries()
for _, child in ipairs(entriesFrame:GetChildren()) do
-- Apenas destruir labels nomeadas "Row1", "Row2", etc (deixar o template intocado)
if child:IsA("TextLabel") and child.Name:match("^Row%d+$") then
child:Destroy()
end
end
end
-- Função para exibir dados da tabela de classificação na tela
local function renderLeaderboard(data)
-- Remover antigas linhas primeiro
clearEntries()
for i, entry in ipairs(data) do
local row = template:Clone() -- Clonar o template oculto
row.Name = "Row" .. i -- Dar a ele um nome único
row.Visible = true -- Torná-lo visível
row.LayoutOrder = i -- Permitir que o UIListLayout o ordene corretamente
-- Formato da tabela de classificação: "1º lugar: Nome de Usuário - 123"
row.Text = string.format("%d%s lugar: %s - %d",
i,
i == 1 and "º" or i == 2 and "º" or i == 3 and "º" or "º",
entry.Username,
entry.Score
)
-- Adicionar os dados à IU
row.Parent = entriesFrame
end
end
-- Loop principal: atualizar a tabela de classificação a cada 3 segundos
while true do
-- Pedir ao servidor os dados da tabela de classificação
local success, data = pcall(function()
return leaderboardRemote:InvokeServer()
end)
if success and data then
-- Mostrar resultados na tabela de classificação
renderLeaderboard(data)
else
warn("Falha ao buscar dados da tabela de classificação")
end
-- Esperar 3 segundos antes de atualizar novamente
task.wait(3)
end