This helped me out in some way but I can’t get it working with my table somehow. I don’t know my problem and it’s frustrating me for the past 2 days…
Hello!
First of all, you should read through
as Blokav already mentioned.
Then you would create the structure inside ServerStorage when game.Players.PlayerAdded
You should also think of an structure of the array as well, I would choose something like this :
local Inventory = {
Apple = 0;
Banana = 0;
Log = 0;
}
When the player leaves with game.Players.PlayerRemoving
you will want to loop through inventory in ServerStorage and create an array which you will save:
local HttpService = game:GetService("HttpService")
local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
game.Players.PlayerRemoving:connect(function(Player)
local dataToSave = {}
for i, v in pairs(game.ServerStorage.Inventory:FindFirstChild(Player.Name):GetChildren()) do
if v:FindFirstChild("Amount") then
dataToSave[v.Name] = v.Amount.Value
end
end
pcall(function()
DataStore:SetAsync(Player.UserId,HttpService:JSONEncode(dataToSave))
end)
end)
And then simply load it everytime player joins as I mentioned already :
local HttpService = game:GetService("HttpService")
local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")
game.Players.PlayerAdded:connect(function(Player)
local newData = DataStore:GetAsync(Player.UserId)
if newData then
newData = HttpService:JSONDecode(newData)
-- load data here, newData.Apple, newData.Banana, newData.Log, they return the amount of each.
else
-- create new data (player joined for the first time
end
end)
Hope I helped.
Problem is that I cannot create a strucute like you did, it won’t work with my system rn. hmm
You’ll want to use the HttpService - it has two functions, :JSONEncode()
and :JSONDecode()
, which allow you to encode and decode tables and strings respectively.
To use this simply pass the table as an argument into JSONEncode and save the returned string. When loading the data, you simply load the string and pass it into JSONDecode to get a table again.
This works for tables with non-numerical keys, but if a table contains more tables (common in object-orientated paradigm) you will need to recursively encode and decode the tables, otherwise data will be lost.
What’s your current system? Is it the ServerStorage one?
Jeah, Ive made a picture from my strucur at the start of this post :))
EDIT: It’s important maybe to know that this doesnt represant the leaderboard or something. I am storing the players inventory like this. So These arent the only thing that the player can have
Yeah! I saw that and I’ve showed you in my code how to build array structure out of that.
I’ll show you again :
local dataToSave = {}
for i, v in pairs(game.ServerStorage.Inventory:FindFirstChild(Player.Name):GetChildren()) do
if v:FindFirstChild("Amount") then
dataToSave[v.Name] = v.Amount.Value
end
end
Now, inside array dataToSave
you have structure like the one I’ve told you about :
{
Apple = 0;
Banana = 0;
Log = 0;
}
Oh so I need to add every item in my game to the dataToSave array?
No, only the ones that are in the ServerStorage as in the player’s inventory.
Then you save/load the array.
The compiler wouldn’t be able to convert to JSON because the table has objects in it. Even if it could, Roblox will automatically convert any variant passed in the SetAsync function into JSON (encoded it), then it is stored on roblox’s servers.
You have to use the magic of serialization and *deserialization. Serialization is basically converting a table into a form it can be saved in. Datastores can’t save objects, so you’ll have to store attributes of the object in a table and save it. When the player rejoins, a new instance of the object will be created and the attributes are set, or whatever.
Your saving portion of your script should look something like this:
function save(player) -- making this as a function so it can be called elsewhere
local save = {Items = {}; Character = {}}
for _, inv in pairs(game.ServerStorage[player.Name]) do
if inv:IsA("StringValue") then -- or whatever type of value object you used for the things like "Apple", "Log"
save.Items[inv.Name] = {Amount = inv.Amount.Value}
end
end
-- serialize the "Character" folder
yourDS:SetAsync("id-"..player.UserId, save)
end
When it comes to loading the data, deserialization comes in, where you reverse the action of serialization that happened.
The loading portion of your should look something like this:
function load(player) -- same reason as the "save" function above
local saved = yourDS:GetAsync("id-"..player.UserId) or {} -- if the first value exists, it'll be assigned to the variable, otherwise an empty table is assigned
for index, v in pairs(saved.Items) do
local v = Instance.new("StringValue")
local amt = Instance.new("IntValue")
v.Name = index
amt.Name = "Amount"
amt.Value = v.Amount
v.Parent = inventory folder for player
amt.Parent = v
end
end
Hope this helps
Alright guys me and @Sougood made it work now, I was very close.
Basicly I check all StringValues inside the players inventory and add this to a table
game.Players.PlayerRemoving:connect(function(Player)
local inv = {}
for i, v in pairs(game.ServerStorage.Inventory:FindFirstChild(Player.Name):GetChildren()) do
if v:FindFirstChild("Amount") then
inv[v.Name] = v.Amount.Value
end
end
pcall(function()
DataStore:SetAsync(Player.UserId,HttpService:JSONEncode(inv))
end)
end)
This is all we need to save the Data as soon as a player leaves
(Please note that this is not that save because Data could still get lost when the server gets shutdowned I believe)
To load the actuall Data we run this If-Statement whenever a player joins
if newData then
newData = HttpService:JSONDecode(newData)
print("Existing Data")
-- load data here, newData.Apple, newData.Banana, newData.Log, they return the amount of each.
-- ima make few examples of here, hope you can continue
if newData.Apple ~= nil then
if newData.Apple > 0 then
print("Found Apple!")
local Apple = Instance.new("StringValue",folder)
Apple.Name = "Apple"
local amount = Instance.new("IntValue",Apple)
amount.Name = "Amount"
amount.Value = newData.Apple
end
end
if newData.Banana ~= nil then
if newData.Banana > 0 then
local Banana = Instance.new("StringValue",folder)
Banana.Name = "Banana"
local amount = Instance.new("IntValue",Banana)
amount.Name = "Amount"
amount.Value = newData.Banana
end
end
.
.
.
--and so on
EDIT: Please note that this is build to work with my system so it might be diffrent for your system! but this is the general way to save a table and load it in!
I get an “Can’t Parse JSON” error.