generic image
Processing...
  • Games
  • Catalog
  • Develop
  • Robux
  • Search in Players
  • Search in Games
  • Search in Catalog
  • Search in Groups
  • Search in Library
  • Log In
  • Sign Up
  • Games
  • Catalog
  • Develop
  • Robux
   
ROBLOX Forum » Game Creation and Development » Scripters
Home Search
 

Re: Datastores Example

Previous Thread :: Next Thread 
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
14 Nov 2016 02:04 PM
Datastores are easy. Don't overcomplicate it. These are the steps towards saving data in a game...

1. When the player enters, get the saved data (if any) and load in the values.
2. Generate the folders inside the player based on their data
3. When the player leaves, get the data and values from inside the player's stats folders, and save it to a table
4. When the data is set, save the table to the users userid
5. You should be using FE or data can be compromised.
6. VALUES MUST BE SET FROM THE SERVER. NEVER LET A CLIENT HAVE POWER TO CHANGE THEIR DATA
7. All of the data is handled with a module script!!!
8. Enjoy!

I have explained each step below...

--SERVER SCRIPT

local DataHandler = require(game.ServerStorage.Modules.DataHandler) --we require the module script

game.Players.PlayerAdded:connect(function(player) --when a player enters load their data
DataHandler.LoadData(player)
end)

game.Players.PlayerRemoving:connect(function(player) --when a player leaves, save their data
DataHandler.SaveData(player)
end)

game.OnClose = function() --if the server crashes for any reason at all, we can make sure the data isn't compromised.
for i,v in next, game.Players:GetPlayers() do
DataHandler.SaveData(v) --We can exploit the fact that a reference to the player will still be available
end
end

--MODULE SCRIPT

local PlayerData = game:GetService('Data StoreService'):GetDataStore('TestData') --Get the data store

local DefaultStats = { --These are the default stats the user gets if they play for the first time
Stats = { --Each leaderstat/folders that you want the player to spawn in with is added here
Powerups = {
HealthBoost = true,
RandomValue = 1,
},
Kills = 0,
Deaths = 0,
Points = 0,
},
--Inventory = {}, --optional
--Character = {}, --optional
}

local PlayerStats = {} --This is where each players data will be saved.
--You can optionally use this to generate the stats in serverstorage

local DataHandler = {}

LoadStats = function(Player)
local UserId = Player.UserId
local PlayerStats = PlayerStats[UserId]
for stats,data in next, PlayerStats do --stats,inventory,character,etc.
local NewStat = Instance.new('Folder',Player)
NewStat.Name = stats --new folder with the name of the stat
for key,val in next, data do --loop through the data in each folder
if type(val) == 'table' then --if its a table, then make a new folder
local NewFolder = Instance.new('Folder',NewStat)
NewFolder.Name = key --set the name of the folder to the container
for key,v in next, val do --loop through the table
if key == 'HealthBoost' then --We can choose what kind of value it will be
local NewVal = Instance.new('BoolValue',NewFolder)
NewVal.Name = key
NewVal.Value = v
else --otherwise it will be an intvalue by default
local NewVal = Instance.new('IntValue',NewFolder)
NewVal.Name = key
NewVal.Value = v
end
end
else --we can directly create the value inside the stat folder
local NewVal = Instance.new('IntValue',NewStat)
NewVal.Name = key
NewVal.Value = val
end
end
end
end

SaveStats = function(Player)
local UserId = Player.UserId --we use userid to make sure we don't overlap data
local Stats = Player:WaitForChild('Stats') --Stats is in our table
for i,val in next, Stats:GetChildren() do --Get each value inside the stat folder
if val:IsA('Folder') then --we treat folders as tables (data containers) like before
for i,v in next, val:GetChildren() do --get the data inside the folder and set to the table
PlayerStats[UserId][Stats.Name][val.Name][v.Name] = v.Value
end
else
PlayerStats[UserId][Stats.Name][val.Name] = val.Value -- set the data to the stat folder
end
end
--if we want to verify that the correct values are set...
for i,v in next, PlayerStats[UserId] do
print(i) --Stats
for j,k in next, v do
if type(k) == 'table' then
print(j)
for key,val in next, k do
print(key,val)
end
else
print(j,k)
end
end
end
end

DataHandler.LoadData = function(Player)
local UserId = Player.UserId
local Data
pcall(function() Data = PlayerData:GetAsync(UserId) end)
if Data then --load in previous data
PlayerStats[UserId] = Data
else --otherwise we load in the default values and save the default stats
local s,e = pcall(function() --Wrap with pcall to prevent an error
PlayerData:SetAsync(UserId,DefaultStats) --save the default stats
end)
if not s then warn(e) end --alert us if an error occured
PlayerStats[UserId] = DefaultStats
end
LoadStats(Player) --load in the default values
end

DataHandler.SaveData = function(Player)
local UserId = Player.UserId
SaveStats(Player) --save the default values inside the player
--After all the data is loaded into the table, we can save it
local s,e = pcall(function() --Wrap with pcall to prevent an error
PlayerData:SetAsync(UserId,PlayerStats[UserId]) --We save the player's individual data
end)
if not s then warn(e) end --alert us if an error occured
end

return DataHandler


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
14 Nov 2016 04:18 PM
b


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:26 AM
b2


Report Abuse
foreverpower is not online. foreverpower
Joined: 05 Feb 2011
Total Posts: 5578
15 Nov 2016 09:28 AM
Use this: http://wiki.roblox.com/index.php?title=API:Class/DataModel/BindToClose
Report Abuse
RubyEpicDragon is not online. RubyEpicDragon
Joined: 02 May 2015
Total Posts: 1211
15 Nov 2016 09:29 AM
Why not letting a client do the data Store?
must you use a module script or is that your choice?
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:32 AM
You should be using a module script so the main server script isnt cluttered.

@foreverdev

what the difference between

game.OnClose

and

BindToClose?

Aren't those the exact same thing?


Report Abuse
RubyEpicDragon is not online. RubyEpicDragon
Joined: 02 May 2015
Total Posts: 1211
15 Nov 2016 09:33 AM
A question. Why playerdata[payer.UserId] and not just playerdata? What are the differences?
Report Abuse
RubyEpicDragon is not online. RubyEpicDragon
Joined: 02 May 2015
Total Posts: 1211
15 Nov 2016 09:33 AM
What will it do?
Report Abuse
foreverpower is not online. foreverpower
Joined: 05 Feb 2011
Total Posts: 5578
15 Nov 2016 09:33 AM
"Why not letting a client do the data Store?"
Is the reason not obvious? Exploiters.

"must you use a module script or is that your choice?"
Of course you don't have to.


Also
"5. You should be using FE or data can be compromised."
No.
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:33 AM
Oh I just saw its deprecated. Thanks for the heads up!


Report Abuse
foreverpower is not online. foreverpower
Joined: 05 Feb 2011
Total Posts: 5578
15 Nov 2016 09:34 AM
@TimeTicks
BindToClose allows multiple functions to be bound to the closing of the game, in case any other scripts are binding a close function.
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:34 AM
playerdata[userid] ensures that the data is not overlapped with another players data.


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:35 AM
@Forever, they should be using fe regardless.


Report Abuse
RubyEpicDragon is not online. RubyEpicDragon
Joined: 02 May 2015
Total Posts: 1211
15 Nov 2016 09:37 AM
So if the player has the user I'd 123456 it would be playerdata.123456?
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:40 AM
This is what the table will look like with multiple ids.

PlayerStats = {
123456 = { --userid so we can prevent overlapping
Stats = {
Kills = 10,
Deaths = 0,
Points = 100,
},
},
654321 = { --userid
Stats = {
Kills = 10,
Deaths = 0,
Points = 100,
},
},
},


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 09:41 AM
And to index the data simply just do

local Data = PlayerData[UserId]

to get the users individual data


Report Abuse
0_1195 is not online. 0_1195
Joined: 21 Dec 2011
Total Posts: 268
15 Nov 2016 10:07 AM
When you create a new folder parented to the player, doesn't that mean the client can edit the data?

local NewStat = Instance.new('Folder',Player)


\_(siggy)_/
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 02:58 PM
Yes. However, with FE, client changes will not affect the value. Only the server can do this. This is why this method is more or less safe. But like I said, if you are paranoid about the integrity of the data, you can store the values in serverstorage, and update the client's stats from there.


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
15 Nov 2016 04:53 PM
b3


Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
17 Nov 2016 01:01 PM
gg


Report Abuse
Dralian is online. Dralian
Joined: 21 Mar 2013
Total Posts: 7624
19 Nov 2016 09:10 PM
actually pretty neat, thank you. haha.
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
21 Nov 2016 12:35 PM
np


Report Abuse
RubyEpicDragon is not online. RubyEpicDragon
Joined: 02 May 2015
Total Posts: 1211
22 Nov 2016 01:07 PM
thx, but can you also show a example of a script that saves the players inventory or backback when they leave? even when the server is closing?
Report Abuse
TimeTicks is not online. TimeTicks
Joined: 27 Apr 2011
Total Posts: 27115
22 Nov 2016 01:47 PM
The example is right there. You literally just grab the items from their inventory just like you would like any other data. And game:BindToClose() is used to save when the server shuts down.


Report Abuse
Lurching_Spark is not online. Lurching_Spark
Joined: 01 Oct 2016
Total Posts: 255
22 Nov 2016 02:18 PM
Grabbing this out of my main script:

game.OnClose = function()
for i, v in pairs(playerdata) do
datastore:SetAsync(i, v)
end
end


Do I write that the same way using BindToClose?
Report Abuse
Previous Thread :: Next Thread 
Page 1 of 1
 
 
ROBLOX Forum » Game Creation and Development » Scripters
   
 
   
  • About Us
  • Jobs
  • Blog
  • Parents
  • Help
  • Terms
  • Privacy

©2017 Roblox Corporation. Roblox, the Roblox logo, Robux, Bloxy, and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.



Progress
Starting Roblox...
Connecting to Players...
R R

Roblox is now loading. Get ready to play!

R R

You're moments away from getting into the game!

Click here for help

Check Remember my choice and click Launch Application in the dialog box above to join games faster in the future!

Gameplay sponsored by:
Loading 0% - Starting game...
Get more with Builders Club! Join Builders Club
Choose Your Avatar
I have an account
generic image