How to save the remaining data in LocalScript when the player leaves the game?

It works, just when you click the stop button (idk how many times I have explained this) It is shutting down the server, so use bindtoclose() to save it.

You shouldnt be doing this because exploiters can fire tampered data. The reason that your playerremoving doesnt work is that your player has left before that event can fire (and this is also why PlayerAdded doesnt fire for you too) Why not have the data on the server at all times? Anyway, if you still want to keep the data on the client then you can try the player removing on a serverscript where you invoke the client for data. But this can also be exploited very easily so the best way would be to not have the data updated on the client in the first place.

I’m aware of that.

In server I’m doing:

game.Players.PlayerRemoving:Connect(function(Player) 
	RemoteEventQuit:FireClient(Player)
end)

… and in LocalScript:

local function Quit(Player)
    SaveData() 
end
RemoteEventQuit.OnClientEvent:Connect(Quit)

… but RemoteEventQuit in LocalScript is not being fired when the player leaves the game…

I asked you to use a remote function not an event
Ask the client for their data and save on the server.

But you should still have the data on the server at all times

I’ll try, tks.

This is impossible because my game will be a simulator that will move thousands of pieces at the same time, at 60 FPS, inside RenderStep, which will generate an absurd overhead of data transmission over the internet between the client and server, creating an unsustainable latency for the gameplay.
In addition, these pieces will only be seen by the current player, it is not necessary to share their visualization with other players.

I will be required to create different techniques in Server, such as periodic “sampling” and auditing the data to see if there is any sabotage.

Uh no, you aren’t getting the point. Because the data is all on the client, you are allowing the player to tamper with the data. You shouldn’t be doing any data-related stuff on the client, instead, do it on the server. You are setting up yourself for a snowball effect of exploitation. I highly suggest that you deal with all this on the server.

Tks, but read my last post.


What exactly are you saving? Are you saving the positions of all of those thousands of parts or what?

I have, make a work around. If you are going to have data on the client, I’m going to be blunt: you are setting up yourself for a bad experience.

periodic sampling

That can cause false positives for players with bad ping

And this is just an XY problem.

If you tell us what you are saving as “data” then ww can help you come up with a solution server sided

Not XY, because I can’t see other more viable solution than leaving the data in LocalScript and saving it to the Server each 30 seconds.

How will I move 10,000 objects through the Server at 60 FPS?

That does not answer my question. What exactly do you need to save? Im pretty sure you dont need to save positions of all 10k parts

That’s exactly what I need. It’s a simulator. Think about something like SimCity or Cities SkyLines. Lot of data. Each piece of data has its importance.

10,000 moving parts

so if your game is like simcity, buildings and houses dont move so whats moving? Cars,NPCs? (Which you dont need to save)

And btw games like simcity already have a streaming system in place which you can also implement to combat the data transmission overhead (so only replicate those parts which can be seen by the player, rest will not move until observed, you can predict where that part wouldve been if it had been moving and move it to that point once)

And besides if you are trying to save buildings and such then you can just use a big part which covers the entire building and save its position instead of saving positions of all parts in the building? (Cuts down your data size by a significant lot)

Of course, I need to save them since their CFrames are vital to game logic.

If I’m going to move 10k pieces via Server in the player’s workspace, let’s do the math:
Even the Server transmits only the CFrame for each object to the player’s computer, there are still around 100 bytes to be transmitted for each object, at 60 FPS. 60 x 100 x 10,000 = 60,000,000 bytes (60 Mb) per second!

Okay then you can implement a streaming system where only the cars that the player can see are replicated. Rest of them doesnt move until the player can see them. You can keep “moving” them on the server by storing their positions in a table and lerping that position instead of their part. Then when the player is close enough to the part to see it, move the part instead of the position we had saved.

And heres a bandwidth optimization thread that has some really useful points especially the way they replicate data from server to client

https://devforum.roblox.com/t/how-we-reduced-bandwidth-usage-by-60x-in-astro-force-roblox-rts/

1 Like

To stop the speculation and get to the facts, I made a simulation by creating 10k objects and moving them:

local RunService = game:GetService("RunService")
local parts = Instance.new("Folder", workspace)

for l = 1, 100 do
	for c = 1, 100 do
		p = Instance.new("Part", parts)
		p.Name = "p" .. l .. "_" .. c
		p.Anchored = true
		p.Size = Vector3.new(3, 3, 3)
		p.Position = Vector3.new(l*4, 3, -c*4-10)
	end
end

local function Render(delta)
	print(math.floor(1 / delta))
	for _, p in pairs(parts:GetChildren()) do 
		p.CFrame += Vector3.new(-0.1, 0, 0)
	end
end

wait(3)
RunService.Heartbeat:Connect(Render) 
  1. Copy this to LocalScript, Publish to Roblox and Run it using Roblox Player. You’ll get something like this:

LOCALSCRIPT:

  1. Now delete the LocalScript and do the same with copying the same script to ServerScriptService:

SERVER:

Do you understand my concern now?

Read my reply, I talk about streaming content I was already aware of your concern.

the blue character is our player. The green parts are the ones that they can see and the red ones are parts which are out of their range so updating those is useless. Now, the count for the green parts is roughly 1000 which is 10x less than what you were previously dealing with! (these parts are rather closely packed, in an actual situation the count would be even less)

now what you can do is tell the client the starting positions of the green parts and let them handle those parts on their machine. Then, to sync the client & server you can ping the client with the position where the parts should be every 10-30 seconds or so. (we know what speed the parts are moving at, so we can very easily calculate the distance s they would have moved in time t) Then when the player leaves you don’t even need to ask them for the positions, you can simply use the syncing function to predict where the parts would have been if they were being updated 60 times a second, and save that data. (This also means that you dont even need to have physical parts on the server, all of this can be handled with a dictionary.)


You should try to update as little parts as possible, updating all 10,000 even without replication is alot for the client to handle, your script activity will be 70%-ish (which is wayyy over the safe limit of 3%)

2 Likes

Sorry for coming back to this topic, I’m struggling to switch everything to Server, but another concern occurred to me:
Even though I do all these tricks to reduce the latency in moving the pieces between the server and the client, it can even work for 1 player. But if the server has for example moving 10 players? Even if I can reduce the moves to 1000 pieces per player, the server will still move 10,000 pieces (1000 x 10 players).
This way, we will still have a lot of latency.
I’ve been migrating all my code that was originally in LocalScript to the server for days, but I’m worried if this won’t be a complete waste of time and then find out that the game will be unworkable…

I didnt ask you to move all of those parts on the server every frame. Let the clients move the parts then every 5-10seconds you can calculate where the parts SHOULD be and ping the clients with that position. Read my post again.

So we know how fast the the parts are moving (say 5units/s) and we know the time (10seconds) so its easy to calculate where the part would have been if it was ACTUALLY moving (distance=speed*time)

So now our part should be at
(lastPosition + distance)

And we fire a remote event to the client with this position to sync the server & client. The parts DO NOT MOVE AT ALL on the server. Infact, you dont even need parts on the server. Just store the positions in a table

1 Like