I want to save the player’s data when this player leaves the game. (BindToClose
runs only when ALL players leave the game, so I’m using game.Players.PlayerRemoving
for that).
Also, to avoid excessive data transfer to DataStore, during the game, I’m using a “Cache”, ie, I’m storing all player’s data from LocalScript to ServerScript, and storing this data in a local variable “Jogo” in ServerScript (which is persistent).
Therefore, the data will be effectively saved (SetAsync) ONLY when the player leaves the game.
The logic
In short, this is the logic:
- Data from LocalScript is sent to ServerScript
- ServerScript keeps this data in a global variable “Jogo”
- This process will repeat until the player leaves the game
When the player leaves the game, the following must occur:
- LocalScript
game.Players.PlayerRemoving
will run and set the final player’s data to be saved - This final data will be sent to Server
- ServerScipt
game.Players.PlayerRemoving
will run and finally save (SetAsync) the player’s data effectively.
The Script
LocalScript:
print("LOCAL Start")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEventCache = ReplicatedStorage:WaitForChild("RemoteEventCache") -- disparado pelo cliente, salva tabela de celulas do jogador atual no cache
local Jogo = "** Local Init Data"
local function Cache() -- will send data to Server for cache
print("LOCAL Cache")
print(Jogo)
RemoteEventCache:FireServer(Jogo) -- send data to Server cache
print("LOCAL: after RemoteEventCache") -- - Here, SERVER Cache should have already been run
end
game.Players.PlayerRemoving:Connect(function(Player) -- when a player leaves the game
print('--------------------')
print("LOCAL PlayerRemoving")
Jogo = "** Data from LOCALSCRIPT must be saved"
Cache() -- força envio do cache (independente dos 5 segundos)
end)
ServerScript:
print("SERVER Start")
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Jogo = "** Server Init Data will be saved" -- player's data (persistent in the Server Script)
local function Cache(Player, Jogo2) -- save player's data in cache (but not SetAsync)
print("SERVER Cache")
Jogo = Jogo2
end
function FlushCache(Player, Jogo)
print("SERVER FlushCache")
warn(Jogo)
local JogoStore = DataStoreService:GetDataStore("Jogo", Player)
JogoStore:SetAsync("Jogo", Jogo)
warn("Saved")
end
game.Players.PlayerRemoving:Connect(function(Player) -- when a player leaves the game
print("SERVER PlayerRemoving")
FlushCache(Player, Jogo) -- SetAsync the current global variable Jogo
end)
game:BindToClose(function() -- no more users (server Shutdown)
print("SERVER BindToClose")
if RunService:IsRunning() and RunService:IsStudio() then -- only when stopping the game in Studio
wait(3) -- will force Studio to wat 3 secs to finish SetAsync in PlayerRemoving
end
end)
ReplicatedStorage:WaitForChild("RemoteEventCache").OnServerEvent:Connect(Cache) -- cliente -> servidor, quando LocalScript altera conteúdo da tabela 'Celula' e
The problem
Running the game (save to Roblox first), here the output:
As shown above, after the LocalScript RemoteEventCache:FireServer(Jogo)
runs, the correspondent Server “Cache” function should be fired.
But not.
Therefore, the final player’s data sent from LocalScript "** Data from LOCALSCRIPT must be saved"
are not being received by the server, which is saving the old data there "** Server Init Data will be saved"
…
What’s wrong? Why the final LocalScript FireServer
is not being received by the Server?
Here the project to download, save, and test:
DataStore.rbxl (22.9 KB)