- [Rojo users] Roblox-Firebase release 1.0.1 available from the Github Release page.
- Roblox MainModule available from my studio’s inventory used in
require(id)
calls.
Roblox-Firebase (“RoBase”) is a standalone API-wrapper module for Firebase’s Realtime Database RESTful API. In the future, I may end up writing a similar module for Firebase’s Firestore service, though this will be at a much later date when I have the time to invest in it.
This is a somewhat niche module, but for those discontented with DataStoreService
and looking for an external database alternative that has a decent free-plan, I believe this is the module for you.
History
Robase initially started as a personal endeavour of mine to improve upon the existing FirebaseService by @MXKhronos which I felt lacked in some areas, namely the lack of a BatchUpdateAsync()
method as well as the lack of cache-support (snapshot
param in my Update methods), among other things I wasn’t particularly content with.
Due to an existing tutorial provided by the aforementioned FirebaseService post, I won’t go into to detail regarding how to set up a Firebase as MXKhronos does a wonderful job at that in his post, however, for those curious you can go here to learn more about Firebase and the uses of its Realtime Database.
Getting your Authentication Token
Open me for help
Video Tutorial to aid
- Click the cog-wheel and then “Project Settings”,
- Click “Service Accounts”,
- Click “Database Secrets”,
- Click “Add Secret” and follow any steps it includes,
- Hover over your newly generated secret and click “Show”
- Click on the clipboard to copy the icon
From there you should go into studio and run the following code snippet into the command bar to upload the auth key to a datastore, this is assuming your game has API access enabled for studio
local DSName = "Enter Your DataStore Name"
local AuthKeyName = "Whatever Your Key Should Be"
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore(DSName)
DataStore:SetAsync(AuthKeyName, "Authentication Key Here")
For consistency sake, you could also put your database URL and any other secrets you plan on generating into the same datastore. I put my URL, auth token, and then my server-database (non-player specific database) unique key all into a datastore.
Hope this helps!
Examples
Within the Github Release, you can find an example script named RobloxFirebaseExample, this script is provided to help guide you in how to utilise this module, however, I will go into some detail below.
RoBase API
API Reference
RobloxFirebase RobloxFirebase
Fields:
string DefaultScope,
string AuthenticationToken,
Functions:
RobloxFirebase __call(string: name, string: scope),
Firebase GetFirebase(string: name [, string: scope]), -- Worth noting scope is *only* optional if provided by RobloxFirebase.DefaultScope
-- it will *not* default and *will* throw an error if not set.
Firebase Firebase
Variant GetAsync(string: key),
bool, Variant SetAsync(string: key, Variant: value [, string: method="PUT"])
bool, Variant DeleteAsync(string: key)
bool, Variant IncrementAsync(string: key [,number: delta])
bool, Variant UpdateAsync(string: key, function callback [, Variant: snapshot=GetAsync(key)])
bool, Variant BatchUpdateAsync(string: baseKey, Dictionary<string, Dictionary> keyValues, Dictionary<string, function> callbacks [, Variant: snapshot=GetAsync(key)])
Simple Example
Code
local ServerScriptService = game:GetService("ServerScriptService")
local DataStoreService = game:GetService("DataStoreService")
--> Storing your credentials in a DataStore is a sure fire way to secure them
--> The client has absolutely no access to the DSS and thus cannot retrieve this information
--> Your Data-Handling should all happen within ServerScriptService too for further security.
local DATABASE_CREDENTIALS = DataStoreService:GetDataStore("DATABASE_CREDENTIALS")
local DB_URL, DB_AUTH = DATABASE_CREDENTIALS:GetAsync("URL"), DATABASE_CREDENTIALS:GetAsync("AUTH")
local RobloxFirebase = require(ServerScriptService["Roblox-Firebase"])(DB_URL, DB_AUTH)
--> local RobloxFirebase = require(5618676786)(DB_URL, DB_AUTH) --> Is an alternative method of requiring the module.
local Database = RobloxFirebase:GetFirebase("") --> Empty name allows access to the full scope of the database unless otherwise specified in DB_URL
--> It is recommended that your DB_URL is the start point of the database so that you can do this.
local PlayerDataFirebase = RobloxFirebase:GetFirebase("PlayerData")
local PlayerData = {
["Level"] = 1,
["Gold"] = 100,
["Stats"] = {
["Speech"] = 10,
["Mining"] = 1
}
} --> !!YOUR KEYS _MUST_ BE STRINGS!!
game.Players.PlayerAdded:Connect(function(player)
local key = tostring(player.UserId).."_Data"
local foundData = PlayerDataFirebase:GetAsync(key) --> Checks "PlayerData"/"PlayerId_Data" for any data
if foundData == nil then
PlayerDataFirebase:SetAsync(key, PlayerData) --> Simple initialisation for their data within the Firebase
foundData = PlayerDataFirebase:GetAsync(key)
end
for key, value in pairs(foundData) do
print(key, value)
end
coroutine.wrap(function()
while wait(60*1) do --> Increment Player Gold by 25 every minute
PlayerDataFirebase:IncrementAsync(key.."/Gold", 25)
end
end)()
end)
game.Players.PlayerRemoving:Connect(function(player)
local key = tostring(player.UserId).."_Data"
local foundData = PlayerDataFirebase:GetAsync(key) --> This would ideally come from wherever you are storing their data,
--> preferably in a Cache and not as stats within their Player instance, but it is your choice.
foundData.Gold += 200
foundData.Stats.Mining += 2
print("Updating...")
PlayerDataFirebase:UpdateAsync(key, function(oldData) --> Literally UpdateAsync() is exactly the same as the DataStoreService
--> The key difference would be the third optional paramater of 'snapshot' which can be used to prevent Roblox-Firebase from perfoming
--> A GetAsync() operation for your 'oldData' and will instead use whatever is supplied.
--> Note: If providing a Snapshot in this method, it must match whatever would be acquired from :GetAsync(key), in this case: "PlayerData/PlayerId_Data"
for newKey, newValue in pairs(foundData) do
oldData[newKey] = newValue
end
return oldData
end) --> You can drop the optional snapshot paramater if not needed/used.
print("Updated.")
end)
Results
(Player spawn database)
(IncrementAsync functionality)
(UpdateAsync functionality in studio-test server)
Closing
Thank you for reading my post and I hope you find use out of my module! I have used this module for about a month now in a live-build game of mine with no issues or data loss, and a further 2 weeks in a test-build place as I slowly write a caching system for said game.
The game is small and exclusive to a group and has ~1k visits and the database is currently sat at ~2.5MB of data used with ~7k ‘rows’ across 133 unique players. With proper data saving and caching it is possible to keep within the 10GB downloads cap but you may have to upgrade to a paid-plan if your game(s) are using more than 10GB downloads per month.
Issue Reporting
In order to report issues, you should be able to file them on the Github Repository or alternatively you can reply to this post.
You are also free to join my studio’s public discord server where you can use the bug-bin channel to report bugs.