You can write your topic however you want, but you need to answer these questions:
What do you want to achieve? Keep it simple and clear!
To save a player’s inventory when they leave the game and rejoin.
What is the issue? Include screenshots / videos if possible.
I don’t know how to do this… I’m very new to scripting.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I looked for YouTube tutorials, but they were for saving things like leaderstats. I couldn’t find any tutorials that helped me.
I want to make a script to save a players Backpack when they leave the game. I currently have a working Leaderstats saving script (from a different tutorial), but no tool-saving script.
I was thinking about saving a number (0 to 1) for each different tool: Player gets Tool1, then the Tool1 datastore is updated to 1, if/when they rejoin, then if Tool1 == 1, then it gives the player Tool1. Probably not the most efficient, but I’m new to scripting…
My current leaderstats saving script (works); if this could be modified to also save tools, that would be great!
local datastore = game:GetService("DataStoreService")
local ds1 = datastore:GetDataStore("WoodSaveSystem")
local ds2 = datastore:GetDataStore("StoneSaveSystem")
local ds3 = datastore:GetDataStore("IronSaveSystem")
local ds5 = datastore:GetDataStore("ExploriteSaveSystem")
game.Players.PlayerAdded:connect(function(player)
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
-------------------Data Saving System-----------------------------
local Wood = Instance.new("IntValue", leaderstats)
Wood.Name = "Wood"
local Stone = Instance.new("IntValue", leaderstats)
Stone.Name = "Stone"
local Iron = Instance.new("IntValue", leaderstats)
Iron.Name = "Iron"
local Explorite = Instance.new("IntValue", leaderstats)
Explorite.Name = "Explorite"
Wood.Value = ds1:GetAsync(player.UserId) or 10
ds1:SetAsync(player.UserId, Wood.Value)
Stone.Value = ds2:GetAsync(player.UserId) or 0
ds2:SetAsync(player.UserId, Stone.Value)
Iron.Value = ds3:GetAsync(player.UserId) or 0
ds3:SetAsync(player.UserId, Iron.Value)
Explorite.Value = ds5:GetAsync(player.UserId) or 0
ds5:SetAsync(player.UserId, Explorite.Value)
-- update data saves
end)
game.Players.PlayerRemoving:Connect(function(player)
ds1:SetAsync(player.UserId, player.leaderstats.Wood.Value)
ds2:SetAsync(player.UserId, player.leaderstats.Stone.Value)
ds3:SetAsync(player.UserId, player.leaderstats.Iron.Value)
ds5:SetAsync(player.UserId, player.leaderstats.Explorite.Value)
print ("saved data")
end)
This is a REALLY bad idea. It will most likely fail due to the amount of datastore calls. In order to save large amounts of data you need to store all of the data in a single table and then only use get and set async once when getting the table.
function SafeSave(Datastore, Key, Value)
local Attempts = 0
local Success = false
local Error = nil
repeat
Attempts += 1
Success, Error = pcall(function()
Datastore:SetAsync(Key, Value)
end)
if not Success then wait(10) end
until
Success or Attempts >= 3
if Error ~= nil or not Success then print("<Error while saving data>\n - "..(Error or "No Error")) return nil end
return Success
end
function SafeGet(Datastore, Key)
local Attempts = 0
local Data = nil
local Success = false
local Error = nil
repeat
Attempts += 1
Success, Error = pcall(function()
Data = Datastore:GetAsync(Key)
end)
if not Success then wait(10) end
until
Success or Attempts >= 3
if Error ~= nil or not Success then print("<Error while retrieving data>\n - "..(Error or "No Error")) return nil end
return Data
end
function SafeUpdate(Datastore, Key, Logic)
local Attempts = 0
local Data = nil
local Success = false
local Error = nil
repeat
Attempts += 1
Success, Error = pcall(function()
Data = Datastore:UpdateAsnyc(Key, Logic)
end)
if not Success then wait(10) end
until
Success or Attempts >= 3
if Error ~= nil or not Success then print("<Error while updating data>\n - "..(Error or "No Error")) return nil end
return Data
end
local ToolsDS = game:GetService("DataStoreService"):GetDataStore("ToolsDS")
game.Players.PlayerAdded:Connect(function(Player)
local SavedTools = SafeGet(ToolsDS, Player.UserId)
if SavedTools ~= nil then
for i,v in pairs(SavedTools) do
local Tool = game.ServerStorage.Tools:FindFirstChild(v)
if Tool ~= nil then
local NewTool = Tool:Clone()
NewTool.Parent = Player.Backpack
end
end
else
SafeSave(ToolsDS, Player.UserId, {})
end
end)
game.Players.PlayerRemoving:Connect(function(Player)
local CurrentTools = {}
local FoundTools = {}
for i,v in pairs(Player.Backpack:GetChildren()) do
if v:IsA("Tool") and table.find(FoundTools, v) == nil then
table.insert(FoundTools, v)
table.insert(CurrentTools, v.Name)
end
end
local Character = Player.Character
if Character ~= nil then
for i,v in pairs(Character:GetChildren()) do
if v:IsA("Tool") and table.find(FoundTools, v) == nil then
table.insert(FoundTools, v)
table.insert(CurrentTools, v.Name)
end
end
end
SafeSave(ToolsDS, Player.UserId, CurrentTools)
end)
I recommend using tables to accomplish this. They essentially allow you to store objects. With a combination of a for loop and a table, you can store data. A brief overview could look like:
Store the player’s tools in a specific directory i.e ServerStorage.
Create a folder when they join, clone any tools they have into that folder, as well as the backpack.
If data doesn’t exist, then give them default tools.
When the player is leaving, loop through the folder and save their tools in a table. Preferably the names of them. Save to the datastore by using UpdateAsync.
Here’s a simple yet helpful tutorial on saving tools by @sjr04.
Here’s one about using DataStore2, which is an essential resource by @Kampfkarren . You can get in on Github.