hi, i am making a game with a stringvalue that needs to be saved. whenever i change the value of the stringvalue, and I leave, the value sets back to the staring stringvalue’s value. any help?
script:
local currencyName = "tool"
local DataStore = game:GetService("DataStoreService"):GetDataStore("TestDataStore")
game.Players.PlayerAdded:Connect(function(player)
local currency = Instance.new("StringValue")
currency.Name = currencyName
currency.Parent = player
local ID = currencyName.."-"..player.UserId
local savedData = nil
pcall(function()
savedData = DataStore:GetAsync(ID)
end)
if savedData ~= nil then
currency.Value = savedData
print("Data loaded")
else
currency.Value = "M4A1"
print("New player to the game")
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local ID = currencyName.."-"..player.UserId
DataStore:SetAsync(ID,player[currencyName].Value)
end)
game:BindToClose(function()
for i, player in pairs(game.Players:GetPlayers()) do
if player then
player:Kick("This game is shutting down")
end
end
wait(5)
end)
hi, its tough to figure out the issue without an error code so I recommend using the fields the pcall return which are success, and error. you should print the second parameter so we can get the error code.
So this block of code is the part that manages loading data, but also manages setting it to a default if the data is equal to ‘nil’.
Not sure what exactly is the value that it sets back to, but if you mean the default string value that you have set it for a new user, which is “M4A1”, then your pcall() that handles retrieving the player’s data is probably returning an error, its simply not caught in the call since it is an isolated pcall() with no variable it can return to.
If you are able to retrieve the 2 returned values that include the success boolean, you can catch it in your code and make it automatically attempt a recall or at least print out its error.
Example of a more reliable pcall() in a function:
function retrieveData()
local success, response = pcall(function()
savedData = DataStore:GetAsync(ID)
end)
if success == false then
print("Data call success returned " .. success .. " retrying call ...")
wait(.05)
retrieveData()
end
end
retrieveData()
Make sure you have API Services enabled as well as the fact that you’re not changing the player’s tool value from the client command bar. I tested the code and it works fine in-game.
I also recommend going with G8Max’s approach with how he handles the pcall.
Just a edit to your function i would add a retries counter to it so just in case you encounter a particularly bad data store you dont exceed the limits
Heres an Edited Version
local Retires = 0
local MaxRetries = 5 -- anything you want
function retrieveData()
local success, response = pcall(function()
savedData = DataStore:GetAsync(ID)
end)
if success == false then
Retries = Retries + 1
print("Data call success returned " .. success .. " retrying call ...")
wait(.05)
if Retires < MaxRetries then
retrieveData()
elseif Retries >= MaxRetries then
Retries = 0
end
end
end
retrieveData()
Your issue is that you are not saving when the game shuts down, you only kick them.
And, I would also set up a loop that saves everyone’s data every X minutes.
local Players = game:GetService('Players')
local DataStoreService = game:GetService('DataStoreService')
local Key = DataStoreService:GetDataStore('DataStore')
local MaxTries = 3 -- Roblox allows you to attempt saving 3 times before the request gets rejected.
local Update_Time = 120 -- Every 120 seconds (every 2 minutes)
--[[ Create a thread that runs alone without affecting the rest of the script --]]
coroutine.create(coroutine.resume(function()
-- Save their data with a loop. Example:
local GetPlayers = Players:GetPlayers()
for i = 1, #GetPlayers do
local Target = GetPlayers[i]
-- Usage: Target.UserId, Target is the player instance.
-- Using numerical loops is actually faster in the long-run,
-- assigning local variables is also faster when accessing them the 2nd time and beyond.
end
end))
--[[ LOAD DATA --]]
Players.PlayerAdded:Connect(function(Player)
local Ok, Result = pcall(function()
return Key:GetAsync(Player.UserId)
end)
if Ok then
if Result then
print('Currently saved:', Result)
else
print('No data has been saved for this player yet!')
end
else
print('Error while retrieving data as DataStores are currently down:', Result)
end
end)
--[[ SAVE DATA--]]
Players.PlayerRemoving:Connect(function(Player)
local Ok, Result
local Tries = 0
repeat
Ok, Result = pcall(function()
Key:UpdateAsync(Player.UserId, function(CurrentValue)
return 123
-- Whatever value you need to store. CurrentValue returns their current saved data (if any, otherwise it's nil).
end)
end)
if not Ok then
wait(1)
end
until Tries == MaxTries or Ok
-- The reason I use a repeat loop is because Roblox sometimes rejects the request, this is not an issue when getting or removing data.
-- You are allowed a "retry" 3 times before Roblox rejects the request.
if not Ok then
print('Error while saving data:', Result)
end
end)
Disclaimer: I am giving you pseudocode, which means a notation resembling a simplified programming language, used in program design.
You may get a better understanding with the given code.
i found out the problem I guess. IDK i changed the script and changed the value from the script and it loads now, thanks to everyone for helping.
script:
local DataStoreService = game:GetService("DataStoreService")
local PlayerCash = DataStoreService:GetDataStore("PlayerCash")
function OnPlayerAdded(player)
local stats = Instance.new("Folder", player)
stats.Name = 'leaderstats'
local Cash = Instance.new("StringValue", stats)
Cash.Name = "$"
Cash.Value = "yo"
local data
local success, err = pcall(function()
data = PlayerCash:GetAsync(player.UserId)
end)
if success then
print("Data loaded!")
if data then
Cash.Value = data
end
else
print("There was an error while getting data of player " .. player.Name)
warn(err)
end
while wait(10) do
Cash.Value = "LOL"
end
end
function OnPlayerRemoving(player)
local success, err = pcall(function()
PlayerCash:SetAsync(player.UserId, player.leaderstats:FindFirstChild("$").Value)
end)
if success then
print("Data saved!")
else
print("There was an error while saving data of player " .. player.Name)
warn(err)
end
end
game.Players.PlayerAdded:Connect(OnPlayerAdded)
game.Players.PlayerRemoving:Connect(OnPlayerRemoving)