Hello there, I am trying to display my Firebase Data to a roblox leaderboard so it can show the Miles a user has and the current frequent flyer tier they are on.
When I do so, it throws two errors, one saying “Module Code did not return exactly one value” and the other error shows “Requested Module experienced an error while loading”.
I have look everywhere for solutions and tutorials on how to make my data connect to a leaderboard but I failed to find any.
--
local defaultDatabase = "https://firebasedatabase.app/"; -- Set your database link
local authenticationToken = "fakekey"; -- Authentication Token
--== Variables;
local HttpService = game:GetService("HttpService");
local globalDataStoreService = game:GetService("DataStoreService");
local FirebaseService = {};
local UseFirebase = true;
local Settings = require(script.Settings);
local globalDataStoreService;
--== Script;
--[[**
Sets whether Firebase's data can be updated from server. Data can still be read from realtime Database regardless.
@param value bool Using Firebase
**--]]
function FirebaseService:SetUseFirebase(value)
UseFirebase = value and true or false;
end
--[[**
Sets whether Firebase's data can be updated from server. Data can still be read from realtime Database regardless.
@param name string Given name of a JSON Object in the Realtime Database.
@param scope string Optional scope.
@returns FirebaseService FirebaseService
**--]]
function FirebaseService:GetFirebase(name, database)
database = database or defaultDatabase;
local datastore = globalDataStoreService:GetDataStore(name);
local databaseName = database..HttpService:UrlEncode(name);
local authentication = ".json?auth="..authenticationToken;
local Firebase = {};
--[[**
A method to get a datastore with the same name and scope.
@returns GlobalDataStore GlobalDataStore
**--]]
function Firebase.GetDatastore()
return datastore;
end
--[[**
Returns the value of the entry in the database JSON Object with the given key.
@param directory string Directory of the value that you are look for. E.g. "PlayerSaves" or "PlayerSaves/Stats".
@returns FirebaseService FirebaseService
**--]]
function Firebase:GetAsync(directory)
local data = nil;
--== Firebase Get;
local getTick = tick();
local tries = 0; repeat until pcall(function() tries = tries +1;
data = HttpService:GetAsync(databaseName..HttpService:UrlEncode(directory and "/"..directory or "")..authentication, true);
end) or tries > 2;
if type(data) == "string" then
if data:sub(1,1) == '"' then
return data:sub(2, data:len()-1);
elseif data:len() <= 0 then
return nil;
end
end
return tonumber(data) or data ~= "null" and data or nil;
end
spawn(function()
globalDataStoreService = FirebaseService:GetFirebase(name, database)
if not(globalDataStoreService:GetAsync(Settings.defaultDatabase, authenticationToken)) then
globalDataStoreService:SetAsync(Settings.defaultDatabase, authenticationToken, {
playersData = {};
});
end;
end);
local commands = {};
commands[Settings.addMiles] = function(client, message, recipient)
if(client:GetRankInGroup(Settings.groupId) >= Settings.minimumRank) then
local arguments = string.split(string.split(message, Settings.prefix .. Settings.addMiles)[2], " ");
table.remove(arguments, 1)
if(string.lower(arguments[1]) == "all") then
for _, currentPlayer in pairs(game:GetService("Players"):GetPlayers()) do
pcall(function()
currentPlayer.leaderstats.Miles.Value = tostring(tonumber(currentPlayer.leaderstats.Miles.Value) + tonumber(arguments[2]));
end);
end;
else
for _, currentPlayer in pairs(game:GetService("Players"):GetPlayers()) do
if(string.sub(string.lower(currentPlayer.Name), 1, #arguments[1]) == string.lower(arguments[1])) then
pcall(function()
currentPlayer.leaderstats.Miles.Value = tostring(tonumber(currentPlayer.leaderstats.Miles.Value) + tonumber(arguments[2]));
end);
end;
end;
end;
end;
end;
commands[Settings.removeMiles] = function(client, message, recipient)
if(client:GetRankInGroup(Settings.groupId) >= Settings.minimumRank) then
local arguments = string.split(string.split(message, Settings.prefix .. Settings.removeMiles)[2], " ");
table.remove(arguments, 1)
if(string.lower(arguments[1]) == "all") then
for _, currentPlayer in pairs(game:GetService("Players"):GetPlayers()) do
pcall(function()
currentPlayer.leaderstats.Miles.Value = tostring(tonumber(currentPlayer.leaderstats.Miles.Value) - tonumber(arguments[2]));
end);
end;
else
for _, currentPlayer in pairs(game:GetService("Players"):GetPlayers()) do
if(string.sub(string.lower(currentPlayer.Name), 1, #arguments[1]) == string.lower(arguments[1])) then
pcall(function()
currentPlayer.leaderstats.Miles.Value = tostring(tonumber(currentPlayer.leaderstats.Miles.Value) - tonumber(arguments[2]));
end);
end;
end;
end;
end;
end;
commands[Settings.enableAutoMiles] = function(client)
if(client:GetRankInGroup(Settings.groupId) >= Settings.minimumRank) then
Settings.automaticMiles = true;
end;
end;
commands[Settings.disableAutoMiles] = function(client)
if(client:GetRankInGroup(Settings.groupId) >= Settings.minimumRank) then
Settings.automaticMiles = false;
end;
end;
game:GetService("Players").PlayerAdded:Connect(function(client)
local miles;
client.CharacterAdded:Connect(function(character)
repeat wait() until(miles);
local currentValue;
for _, currentChild in pairs(script:WaitForChild("Configuration"):WaitForChild("Tickets"):GetChildren()) do
if(currentValue) then
if(currentChild.Value > currentValue.Value) then
if(tonumber(miles.Value) >= tonumber(currentChild.Value)) then
currentValue = currentChild;
end;
end;
else
if(tonumber(miles.Value) >= tonumber(currentChild.Value)) then
currentValue = currentChild;
end;
end;
end;
if(currentValue) then
currentValue:FindFirstChildOfClass("Tool"):Clone().Parent = client.Backpack;
end;
end);
client.Chatted:Connect(function(message, recipient)
if(message) then
if(string.split(message, Settings.prefix)[1] == "") and (string.split(message, Settings.prefix)[2]) then
if(string.find(message, Settings.prefix .. Settings.addMiles)) then
commands[Settings.addMiles](client, message, recipient);
elseif(string.find(message, Settings.prefix .. Settings.removeMiles)) then
commands[Settings.removeMiles](client, message, recipient);
elseif(string.find(message, Settings.prefix .. Settings.enableAutoMiles)) then
commands[Settings.enableAutoMiles](client);
elseif(string.find(message, Settings.prefix .. Settings.disableAutoMiles)) then
commands[Settings.disableAutoMiles](client);
end;
end;
end;
end);
repeat wait() until(globalDataStoreService);
local leaderstats;
if(client:FindFirstChild("leaderstats")) then
leaderstats = client.leaderstats;
else
leaderstats = Instance.new("Folder", client);
leaderstats.Name = "leaderstats"
end;
if(Settings.showRank) then
local rank = Instance.new("StringValue", leaderstats);
rank.Name = "Rank";
rank.Value = "Guest";
pcall(function()
rank.Value = client:GetRoleInGroup(Settings.groupId);
end);
end;
miles = Instance.new("StringValue", leaderstats);
miles.Value = "0";
miles.Name = "Miles";
local _, errorMessage = pcall(function()
local currentData = globalDataStoreService:GetAsync(Settings.defaultDatabase, authenticationToken);
if(currentData.playersData[tostring(client.UserId)]) then
miles.Value = tostring(currentData.playersData[tostring(client.UserId)].miles)
end;
end);
local configurationFolder = Instance.new("Configuration", miles);
local class = Instance.new("StringValue", configurationFolder);
class.Name = "Class";
while wait(Settings.secondsPerMiles) do
if(Settings.automaticMiles) then
miles.Value = tostring(tonumber(miles.Value) + 1);
end;
end;
end);
game:GetService("Players").PlayerRemoving:Connect(function(client)
local _, errorMessage = pcall(function()
globalDataStoreService:UpdateAsync(Settings.defaultDatabase, authenticationToken, function(oldData)
local newData = oldData;
newData.playersData[tostring(client.UserId)] = {
miles = tonumber(client.leaderstats.Miles.Value);
};
return newData;
end);
end);
if(errorMessage) then
print("Failed to save data from: " .. client.Name);
error(errorMessage);
else
print("Data from " .. client.Name .. " was saved with success");
end;
end);
end
I had to replace the link and the key with a fake one so no one would change the data.