Robase - A ROBLOX wrapper for Firebase


Roblox-Firebase

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

  1. Click the cog-wheel and then “Project Settings”,
  2. Click “Service Accounts”,
  3. Click “Database Secrets”,
  4. Click “Add Secret” and follow any steps it includes,
  5. Hover over your newly generated secret and click “Show”
  6. 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

RobloxFirebaseExampleDatabase
(Player spawn database)

RobloxFirebaseExampleDatabaseIncrementedGold
(IncrementAsync functionality)

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

49 Likes

Seems like a cool module but im not sure how would I get my AUTH in firebase.

All I see is this


https://gyazo.com/ca8059fb3b19a9bdd6a6a8981ca56d54

I usually go in testmode for firebase in javascript so I dont really know how to do this. It would be great if you helped me.

Hello! I also had some trouble finding it initially too when following the old post, so I’ll update my post to include the following help:

  1. Click the cog-wheel and then “Project Settings”,
  2. Click “Service Accounts”,
  3. Click “Database Secrets”,
  4. Click “Add Secret” and follow any steps it includes,
  5. Hover over your newly generated secret and click “Show”
  6. 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!

1 Like

Thanks! I’ll be using this module for players searching up data of other players. Since roblox datastores are pretty inefficient for it.

Also useful for datastore backups so basically if a player reports a dataloss I can see his last saved value in firebase and see if the amount he told is reasonable.

1 Like

Firebase also allows for manual input on data too (so long as the current key isn’t too large in rows) which is super handy for reverting data.

I believe you can also use it for special timed events too (with manual input) so you don’t need to update the game and it works live, but I haven’t gotten to that far into it yet :smiley:

I first started this because I got frustrated at the storage limit on datastore keys and I figured creating some sort of system using OrderedDataStore and os.date() to be convoluted for the goals I was trying to achieve (just a mega dump of every player’s data in full and player’s simply having pointers to this data) and hence I came across Firebase and FirebaseService and developed my own (hopefully) improved version :slight_smile:

1 Like

Very nice stuff :ok_hand: . Maybe people willl stop using trello as a database when they find this. :joy:

2 Likes

Discussed this in the opensource community discord and I already have a name for a trello API wrapper project :joy: Thank you though!

Im not sure if this is possible, but when I used javascript with firebase (on the web), I was able to do something similar to OnUpdate() which fired every time the key was updated, is something like this feasible in this module, it would be a cool addition.

OnUpdate() which fired every time the key was updated

I’m not entirely sure, I would have to look further into the RESTful API for Realtime Database, but as far as I am aware this isn’t possible.
An alternative, however, would be writing an interface for Robase and having Signals for keys and attaching a function to run when they do change. As stated in the post though, saving upon data change is not at all recommended as you will eat through your download cap - I tested this and within ~2.5 weeks I had to disable the database before it encroached upon the limit.

Also, apologies for the late reply, I have been feeling under the weather and swamped with work, appreciate the suggestion though!

1 Like

Really cool module, I’ve been using it for my games data storing.

The only criticisms I have are that I think you should probably use promises over pcalls and for the code to be a bit easier on the eyes. Some code needs to be spaced out.

Otherwise, as I said, a great module!

1 Like

This is the plan for a future update, currently my PC is bust and I need to do some repairs, on top of this I’m unable to travel home due to Covid-19 restrictions and me being in a different country.

I have a lot of improvements to make on this that I plan to begin when I get the chance, thanks for the input!

1 Like

what… I’m very confused.

Firebase is migrating to a new database authentication system. This is completely fine though, as deprecated does not mean removed!

Video tutorial:

1 Like

Screen Shot 2021-01-30 at 11.12.52 AM

What do I use for Secret Key here?

You don’t need Database secrets, follow the video tutorial provided to access your auth key.

But there is like nothing there I am confused.

1 Like

Oh my god thank you so much. Really funny, since last week I spent ages creating my own site to use as an API to update my firebase storage from website. You’re a lifesaver!

1 Like

Thank you kindly for creating a video tutorial, I have now added it to the post under “Getting your authentication token”.

I’m glad that this is of use to you and I hope it’s easy to use and work with, any problems don’t hesitate to ask here, message me, or use the reporting issues section under the post!

1 Like

Does this module/wrapper help handle or cache up http requests?

Firebase allows updating multiple arrays in a single request, just curious if you’re helping to keep HttpService activity down by grouping multiple requests into one every few seconds?

I’m not sure how well this would handle 70 players joining at once and grabbing data for many people.