LocalScript FireServer not firing when player leaves the game

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:

  1. Data from LocalScript is sent to ServerScript
  2. ServerScript keeps this data in a global variable “Jogo”
  3. This process will repeat until the player leaves the game

When the player leaves the game, the following must occur:

  1. LocalScript game.Players.PlayerRemoving will run and set the final player’s data to be saved
  2. This final data will be sent to Server
  3. 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:

image

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)

2 Likes

This is probably happening because the player doesn’t exist anymore by the time the RemoteEvent reaches the server, so there’s no player for the OnServerEvent to use, therefore it doesn’t get fired. Why are you doing it this way anyways? This leaves player data vulnerable to exploiters. You should look into better solutions; you don’t need to save player data immediately! You can just keep it stored on the server and have an autosave, like what Save your player data with ProfileService! (DataStore Module) (ProfileService) does.

1 Like

Ok, I think I’ll have to rethink the entire logic. Thanks.

1 Like