SimplyStore
SimplyStore is a data storing system for games. The system’s goal is to be as easy and intuitive as possible.
What Does It Do?
SimplyStore saves and loads players’ leaderstats folders. When a new player joins, their data is retrieved, created, then added to the player.
This removes may of the dependencies and complexities of other data storing systems: once the leaderstats folder is added, the data is loaded and can be accessed from anywhere.
Timeline:
1. Player Added
2. (Delay) Data retrieved
3. Data created
4. Process Function*
5. Data added to Player
* [OPTIONAL] The process function is for versioning (updating your data structure to the newest layout).
Supported Instances
All value instances are supported. In addition to value instances, three container type instances are supported: Folders, Configurations, and Models.
More Details
Edge cases:
ObjectValues’ values don’t save and are loaded as nil. This is because saving a reference to an object between games is not possible.
Unfortunately there is a maximum table depth in datastores, so there is a maximum ancestry depth in SimplySave. Don’t go past about a dozen ancestors.
Why SimplyStore?
As mentioned above, SimplyStore is meant to be easy and intuitive. All the DataStore code is done automatically behind the scenes.
In addition to this, SimplyStore uses DataStore2 under the hood. Not only does this make SimplyStore reliable*, it means you can use SimplyStore and your own DataStore2 code, without running into read and write limits.
* Although SimplyStore has been tested, it has yet to be used in any large games. It could potentially have bugs that haven’t been fixed yet. If you find a bug, please message @PersonifiedPizza.
Showcase
As an example, I made a simple game using SimplyStore. This game has a few simple game elements that use data storing: daily chests, single time collectable items, and checkpoints. It also has a nice animated loading screen. You can check that out here: SimplyStore (Example Game) - Roblox
Insert the Script into either ServerScriptService or the Workspace
Adjust the default data
The default data is a folder called “DefaultData” inside the SimplySave script. When a new player joins the game, their leaderstats folder is loaded with the default data.
To change the default data, just add what you’d like inside leaderstats to the folder. This could be a Folder called “Data” or an IntValue called “Coins”
If API services aren’t enabled:
If you haven’t yet, publish the game to access the game settings menu
Go to the security tab, and check the box to enable API services
Don’t create leaderstats yourself. SimplySave does that for you.
If a value instance doesn’t exist and you want to set it, just create it and continue with your code.
To store data that doesn’t show up on the leaderboard, use a container Instance. In the examples, the internal data is inside a Folder called “Data” that’s parented to leaderstats.
Amazing, just a quick question though. Can i make a new value, and put it inside someone’s leaderstats mid session, and when they leave, they still have the stat?
Sounds interesting enough!
I hate to deal with DS, this is where my game projects usually ends
So I give it a chance (and a big like as well!), thank you for sharing!
Here’s how the system works: the system adds a leaderstats folder with the previous data to the player (after a short data request delay); you can add, delete, reparent, and change any Values and Folders(*) inside leaderstats; then when the player rejoins the process repeats.
(*) also Configurations and Models (as in the container, not like parts and stuff)
Something to note:
Like DataStore2 (because it uses DataStore2), to save in studio add a BoolValue to ServerStorage named “SaveInStudio” and set the BoolValue to true/on/checked (this will make studio take a tiny bit longer to close)
For example, here is some code you could use:
Code
local Players = game:GetService("Players")
-- When a player is added:
Players.PlayerAdded:Connect(function(player)
-- Wait for leaderstats to be added by system
local leaderstats = player:WaitForChild("leaderstats")
-- See if the player already has a coins value from their last game
local coins = leaderstats:FindFirstChild("Coins")
-- If they don't have a coins value, add one:
if not coins then
coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
end
-- While the player is in the game, give the player 50 coins every 5 seconds
while player do
coins.Value += 50
task.wait(5)
end
end)
In 14 lines, you can create a saving coins value and give players coins for how long they play.
Yep! It’s sort of like a wrapper for DataStore2. All the data storing is done by the system, so all you need to do is get leaderstats and manage the data inside of it.
in developing the data get’s a bit clogged lol, but anyways it’s a good module, you just have to reset the player’s data with manually putting the values and stuff into the player.
You can also use the DefaultData folder to add default data to the player. For example, you could add an IntValue named “Coins” to the default data, then when players join they get an IntValue named Coins.
I’d also recommend making/using a function called findOrCreate to simplify the code:
local function findOrCreate(instance, name, type, value)
local found = instance:FindFirstChild(name)
if not found then
found = Instance.new(type)
found.Name = name
if value then
found.Value = value
end
found.Parent = instance
end
return found
end
Then you can just use that function to get values:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
local leaderstats = player:WaitForChild("leaderstats")
local coins = findOrCreate(leaderstats, "Coins", "IntValue")
while player do
coins.Value += 50
task.wait(5)
end
end)
well, if you already had some values stored it wouldn’t give you new values that are in the default
even tho, i can just add a check and then add it, it would be nice if this was done by default.
game.Players.PlayerAdded
and then you go trough their leaderstats and compare the default leaderstats to make sure none are missing, ye?
Just a suggestion tho.
Edit: How can i wipe the datastore? (delete)
You could do this by adding some code to the built in process function:
Process Function Code
local simplyStoreScript
do
simplyStoreScript = game:GetService("ServerScriptService"):FindFirstChild("SimplyStore", true) or game:GetService("Workspace"):FindFirstChild("SimplyStore", true)
if not simplyStoreScript then
error("Process function couldn't find the \"SimplyStore\" script!")
end
end
-- Couldn't think of a descriptive name. Function abstracted anyways.
local function copyPasta(copy, paste)
for _, copyChild in ipairs(copy:GetChildren()) do
local pasteChild = paste:FindFirstChild(copyChild.Name)
if not pasteChild then
pasteChild = copyChild:Clone()
for _, subPasteChild in ipairs(pasteChild:GetChildren()) do
subPasteChild:Destroy()
end
pasteChild.Parent = paste
end
copyPasta(copyChild, pasteChild)
end
end
local function UpdateWithDefaultData(leaderstats)
local defaultData = simplyStoreScript.DefaultData
copyPasta(defaultData, leaderstats)
end
local function process(leaderstats)
UpdateWithDefaultData(leaderstats)
return
end
return process
Then removing one line of code from the SimplyStore script:
script.DefaultData:Destroy()
--script.DefaultData:Destroy()
(line 22)
(If you don’t see that line around line 22, that’s probably because I’m removing it from new versions of SimplyStore. There isn’t a super good reason to keep that data only inside the script, and it’s nice to have it accessable)
Edit:
Changed that line for new SimplyStores.
Hello! I already have a leaderstats folder, but whenever I join, there is another leaderstats folder. I only want the one I made for a specific reason, how can I make it not make another leaderstats through the code that you made? Or at least be able to change the name of the leaderstats folder that is being created.
The code automatically creates a leaderstats folder. There are duplicates because your code creates one then SimplyStore creates one.
To change your code, instead of creating a new leaderstats folder, just use player:WaitForChild("leaderstats"). This gets the synced folder that SimplyStore creates and allows your code to use that instead.
You also need to get synced values. When the player is added, there is a slight delay, then the leaderstats folder is added with all of the old Values. Before creating new values, you’ll need to check if that value already exists from the last session.
Here is a code example (with too many comments ) from above:
local Players = game:GetService("Players")
-- When a player is added:
Players.PlayerAdded:Connect(function(player)
-- Wait for leaderstats to be added by system
local leaderstats = player:WaitForChild("leaderstats")
-- See if the player already has a coins value from their last game
local coins = leaderstats:FindFirstChild("Coins")
-- If they don't have a coins value, add one:
if not coins then
coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats
end
-- While the player is in the game, give the player 50 coins every 5 seconds
while player.Parent == Players do
coins.Value += 50
task.wait(5)
end
end)
Before creating a coins value, the code needs to check if one already exists from the last session.