Hello Developers! I’m a fairly new addition to the ROBLOX devforums and I’ve noticed that there isn’t any “real” tutorial on the ROBLOX datastore systems. I thought I could create a simple handler myself and allow me to share it with the community and get feedback so I can improve the system. After all, life is a continuous learning process, and I myself wish to learn to make things better and give back to the community. With that being said, I wanted to create my very first tutorial on this forums featuring the datastore handler script I created. So let’s go!
Item/s to Grab:
Important Information to Note
- The documentation is located in the Storage Module for future reference.
- This is my first tutorial, so I apologize if it’s bad. Feel free to hit me up in my DMs on ways to improve this tutorial, or the materials I’ve provided. It’ll benefit me and the community!
- You should take this tutorial and build upon it. I hope that you could make use of what I have for you and let me know what you’ve done with it!
Documentation Expanded
Function #1
GetData
parameters: integer (UserId)
return: table
purpose: Grabs a specific table that associates with the userid.
This function grabs the data for a specific user (given by their UserId). The data is expected to already have been loaded upon the player’s entrance (see function #3).
Function #2
SaveData
parameters: integer (UserId)
return: table
purpose: Saves the data to the datastore. Only used when player leaves.
This function saves the data to the ROBLOX datastore. This should only be used when the player disconnects from the session, or when the autosave runs. It returns absolutely nothing (nil) because there is no need to.
Function #3
LoadData
parameters: integer (UserId)
return: table
purpose: Loads the data from the datastore, or creates a brand new one. Only used when player joins.
Loads a specific players data (given by UserId) from the ROBLOX’s datastore. If there is no data, it’ll create a fresh new data. It returns absolutely nothing (nil) and the data can be grabbed by using function #1.
Function #4
UpdateData
parameters: table (Data to update)
return: table
purpose: Updates the table in storage to the edited table.
This function updates the old data with the newly edited data. The new table is sent over and the storage will update it. However, it does not save to the ROBLOX datastore (see function #2).
Function #5
RemoveData
parameters: integer (UserId)
return: table (old data)
purpose: Removes a data from the datastore
This function deletes the data from the datastore.
Function #6
SaveAllData
parameters: nil
return: nil
purpose: Saves all data in current game
This function will save all data that exists in the current game.
How to Edit Data
Under line 57 of the Storage module under the handler script, you should see a table that looks like this by default:
You can add in more information as you please. For example, if you want to add in an arrest time into the system, you could make it as such:
local tab = {
name = player.Name,
userId = player.UserId,
arrestTimer = 0
}
What’s already given and examples
In the main script, the loading and the saving is already handled for you when the player joins and leaves. You can add in an auto save code if you wish just in case something fails.
To use this, you simply need to require the module and run the functions as provided in the documentation. Line 8 of the main script gives an example of requiring the module.
Then using the variable you defined, you can run the functions as used in the main script as well.
Reading the Script
In this section, I am going to attempt my best to explain what you see in this model, and what the script does, hopefully decoding it for new and novice scripters so they can learn from this, and possibly make their own system!
Let’s jump into the cake. When you first insert the model to studio, you’ll notice three different scripts: one global script, two children module scripts.
DatastoreHandler.lua
Lines 1-8 are comment blocks that explain where the documentation is located as well as credits and the last time the code was updated.
Line 10 gets the module using the require() function to get the module “Storage” and assigns it to a variable called storage.
Once the variable has been defined, we’re finally able to use the module functions, as listed in the documentation above. In this script, by default, when the script first runs, it’ll load the data for every player currently in the game (lines 13-17). Additionally, when a new player is added, it’ll load their data (lines 19-21) or when a player leaves, it’ll save their data (lines 23-25).
Lines 27 to 29 has been added in a case where the server crashes, it will push all existing data to the datastore. This code has not been tested and should not be relied upon.
Settings.lua
When you open this module script, all you see is a table with two keys and values. This module is used for setting the key and the version, to which the datastore service will use. This module is only called by Storage.lua that is explained after this section.
Storage.lua
This module script does all the fun work for you! It contains all the functions that were listed in the documentation above and runs accordingly, to which we will briefly cut down upon.
From line 43 to line 44, we have two important variables being defined. The first variable (storage) is a table where all the data of the players in-game is being held, ready for grabs with the GetData function. The second variable (settings) just grabs the table from the settings.lua module that we covered prior.
Line 46 to line 47 is where the DataStoreService is finally accessed with a unique name that was given in the settings.lua module.
Line 49 is a function that creates a fresh new data, and is only called upon when there’s an attempt to get the existing data of a user, but does not exist in the GetData function. Line 62 is where the new data is made and saved onto the datastore using SetAsync().
Now, we finally dig into the functions that are described in the documentation!
Line 76 is the start to the GetData() function. It is called whenever a script needs the current data of a user. It doesn’t use the datastore function, rather simply goes through the table, fetches the data, and returns a table.
Line 87 is the start to the UpdateData() function. Similarly, this function does not use the datastore function either. From the table that all the data is stored, it retrieves the old data, deletes it, and replaces with the new data that is provided in the parameter.
Line 99 is the start to the SaveData() function. This is typically called when a player leaves the server or when an auto-save function runs. This function grabs the data from the table and saves it to the datastore (line 95 to line 101). To prevent data-loss (as mentioned in the wiki), it uses the UpdateAsync function of the datastore.
Line 122 is where the LoadData() function comes in. This is typically called when a player joins the server and their data needs to be loaded. The function uses the GetAsync function of the datastore to get the players data. If there is no data, it will create a fresh new data using the createData() function we described earlier.
Line 134 is where the DeleteData() enters. This functions serves the purpose to deleting a data that the game no longer needs. It will delete the entire data and set it to nil. When GetAsync() is called upon the data after being deleted, it will then be returned as nil
.
Line 141 is the start to the SaveAllData() function. This function serves to push all existing data in the game to the datastores. This is designed for auto-saves at a certain integral or when the game closes. You should not depend on this code, rather you should use the SaveData() function instead.
Update Logs
[Model Update] September 6, 2017 (16:15 PST) - The save function now uses UpdateAsync rather than SetAsync, as suggested and recommended by @Ripull.
[Forum Update] September 6, 2017 (16:47 PST) - Added a description of what is inside the scripts and explaining what they do, as suggested by @Proxidius. First tutorial, any edits/corrections/suggestions/criticisms is appreciated!
[Model & Forum Update] October 27, 2017 (15:31 PST) - Included a RemoveAsync() [DeleteAsync] to the datastore module and updated the documentation and reading the script on the forum. Some typos were fixed.
[Model & Forum Update] June 7, 2018 (00:59 PST) - Added SaveAllData() to the datastore module. Functions are now called via semicolons instead of periods (old: module.GetData(id); new: module:GetData(id)). UpdateData(), SaveData(), and LoadData() function now return a table. Documentation updated both on forum and on the script.
Thank you for allowing me to give you a tutorial on the datastore handler I’ve created. I hope that I was able to be clear enough and I am willing to take constructive criticisms. I am willing to improve on this model as well as tutorial for the better of me and everyone else. Enjoy!