USING AND MAKING DATASTORES IN OOP (OBJECT-ORIENTED PROGRAMMING)
0. Quick Info
- 0.1
I’ve had problems with doing this, and I have made several attempts, but then I eventually figured it out, with the help of JonByte. So I thought I’d share my knowledge. Also keep in mind that none of this needs to be the exact same thing, you’re free to use your own methods on how you do it. - 0.2
This article will cover on how you can utilise Object-Oriented Programming, for DataStores specifically. And there will be 2 segments: Saving it, and loading it. Or in OOP term, creating it, saving it, and loading it.
You’ll need to know these things in order to be able to follow up and understand this tutorial properly.
-
Lua (obviously, but in Roblox form though)
-
How ModuleScripts work
-
Object-Oriented Programming (Check out JonByte’s tutorial)
-
DataStores
-
That’s all!
INTIALIZATION
First you’ll want to create a ModuleScript and put it in ServerScriptService or ReplicatedStorage. Call it whatever you want, but I’ll be naming mine [color=red]PlayerData[/color].
Oh, hey, you’ve opened the ModuleScript, you’re one step ahead (or you’re not…)
If you have experience with Object-Oriented Programming, you’ll probably know what to do at the start.
local PlayerData = {};
PlayerData.__index = PlayerData;
function PlayerData.new(player)
--empty
end
Now that’s a good way to set it up. Of course, we’ll also want to set its dictionaries/properties and put in the datastore.
local PlayerData = {};
PlayerData.__index = PlayerData;
function PlayerData.new(player)
local LocalData = {};
LocalData.Player = player;
LocalData.Key = player.UserId.."-cash"; --concatenate it to not overwrite other datasaves
LocalData.Value = player.leaderstats.Cash.Value --get the leaderstats cash's value
LocalData.DataStore = game:GetService("DataStore"):GetDataStore("Cash");
setmetatable(LocalData, PlayerData);
return LocalData;
end
We’ll of course be indexing our datastore inside the player data function for more accessibility (and so that we don’t occupy space for code, haha)
Now what next? Oh you know what’s next - our custom methods.
CREATING THE METHODS AND SETTING IT UP
Exciting, right? Has to be one of the most fun aspects I find in Object-Oriented Programming. You get to make your own methods and set what it does, what happens etc. etc.
We’ll want these:
A Load method,
A Save method,
Parameters for the methods (easy, don’t know why I had to add this in)
So let’s make it, starting with the Save function.
function PlayerData:Save()
local savedData;
local success, err = pcall(function()
savedData = self.DataStore:SetAsync(self.Key, self.Player.leaderstats.Cash.Value);
end)
if success then
if savedData then
print("Data saved.");
end
else
warn("There was a problem with saving your data");
warn(err);
end
end
We don’t really need to wrap this in a pcall (at least I think so) so feel free to not, I just did it to be safe I guess.
Then we have to create the Load method, of course, which should be easy.
function PlayerData:Load()
local Result;
local success, err = pcall(function()
Result = self.DataStore:GetAsync(self.Key);
end)
if success then
if Result then
print("Current cash: "..Result);
self.Player.leaderstats.Cash.Value = Result;
end
else
warn("There was an error with fetching your data");
warn(err);
end
end
Now this one [color=yellow]has[/color] to be wrapped in a pcall. You never know, getting the data might fail for some reason and the whole script might break. But then, this is how we’ll load the data and apply the loaded data to the cash. This should be self-explanatory if you know how DataStores work or if you’ve worked with them before.
SETTING THE SCRIPT
Now that we’ve done almost everything, it’s time to move onto a regular script, which I’ll be putting in ServerScriptService. Name it anything you want, I’ll be naming it psadfjlkasjdflkjxd;lcvkjlkjsldkf
.
Now you may think, the first thing we’d want to do here is to require the ModuleScript. Yes, that’s [color=red]one[/color] of what we’re going to prioritize, but let me remind you: we haven’t made leaderstats or cash for the player yet. So let’s do that.
local Players = game:GetService("Players");
local PlayerData = require(script.Parent.PlayerData);
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder", player);
local cash = Instance.new("IntValue", leaderstats);
cash.Name = "Cash";
end)
Now that that’s done, let’s now use the PlayerData module for when the player is added.
local Players = game:GetService("Players");
local PlayerData = require(script.Parent.PlayerData);
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder", player);
local cash = Instance.new("IntValue", leaderstats);
cash.Name = "Cash";
local newPlayerData = PlayerData.new(player);
newPlayerData:Load() --load in case
end)
Easy, and in just a few lines! But then, we [color=red]forgot something[/color]. We haven’t made anything that removes the player’s data upon leaving. Don’t skim out on this, this is important if you don’t want any memory leaks.
Now you may ask, how would we get the specific PlayerData object that we’ve created that the player owns? It’s simple. We’ll create a dictionary that will store it as a key, with the player’s user id being the name of that key.
local Players = game:GetService("Players");
local PlayerData = require(script.Parent.PlayerData);
local allPlayerData = {};
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder", player);
local cash = Instance.new("IntValue", leaderstats);
cash.Name = "Cash";
local newPlayerData = PlayerData.new(player);
newPlayerData:Load() --load in case
allPlayerData[player.UserId] = newPlayerData; --make a new key, set newPlayerData as the value
end)
Now we have access to that specific data module just by using the player’s ID! Nothing complicated, nothing hard, just simple. Now let’s save the data then delete the data off the current game session/server to prevent memory leaks or any unwanted unintentional issues in the future.
local Players = game:GetService("Players");
local PlayerData = require(script.Parent.PlayerData);
local allPlayerData = {};
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder", player);
local cash = Instance.new("IntValue", leaderstats);
cash.Name = "Cash";
local newPlayerData = PlayerData.new(player);
newPlayerData:Load() --load in case
allPlayerData[player.UserId] = newPlayerData; --make a new key, set newPlayerData as the value
end)
Players.PlayerRemoving:Connect(function(player)
local pData = allPlayerData[player.UserId]; --search for player's data using user id
if pData then
pData:Save() --save data
allPlayerData[player.UserId] = nil; --remove it
end
end)
CONCLUSION
Thanks for reading my horrible and poorly-written guide. Hope it helped!
[color=lime]Feel free to PM me if you’re having an issue somewhere[/color].