How to prevent exploits on a purely client sided minigame?

I have a minigame that basically spawns pizzas onto a conveyor belt, they move across while you have to place toppings on them. I have this fully running on the client, as multiple players can be playing the same game at once (and thus pizzas spawning on the server would cause multiple pizzas on the conveyor for multiple players)

So I have to run the pizzas on the client, topping placement, etc. on the client. What can I move to server? I also don’t want to have to contend with latency between remotes.

So the idea of firing a remote everytime the pizza hits the end, and them having a timer or something to make sure the second pizza isn’t being done too quickly is out of the question. Firing a remote for every single pizza would cause huge delays.

My problem is preventing exploiters from basically giving themselves high scores and thus a ton of cash. What ways can I go about fixing this issue?

You can still run the minigame on the server- just hide the other player’s pizzas/orders on the client making it invisible to others.

This can be done with a firetoallclients/etc.


Why send it to one client, that would take more work, you’d want to do FireAllClients:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local secondsRemaining = 5
-- Fire the remote event every second until time expires
for t = secondsRemaining, 1, -1 do
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local function onTimerUpdate(seconds)
-- Call "onTimerUpdate()" when the server fires the remote event

Codes from developer hub:

More about FireAllClients:

Essentially, handle all effects on client like movement/grabing toppings effect/putting on toppings (On client, hide other player’s pizzas). Handle important data/what they’re doing on server, pizzas, etc.

1 Like

Well let’s say I do spawn pizzas from server, and ‘name’ the players name or tagging them to the player, so I can keep track of whose pizzas are whose. Next problem arises with toppings. clicking and dragging toppings would require constant remote event fires to check if they have dragged it and let go over the pizza part. Like I said, I don’t want constant remotes firing or even having several remotes for just 1 minigame.

Toppings wouldn’t require much. Handle the dragging on the client as usual and only send a remote event to the server if the player places the toppings. You can handle this all on a single remote if you wanted to. And if you’re really worried, you can “shrunk” the data down to bools or such (i forgot but something like serialization?)

As long as it isn’t too much data, the server can handle it. And I don’t think the names of toppings with a 1 or 0 will be much data.

Handle dragging on client,ONLY send a remote event from client if the player places it on the pizza.
All effects done on client, all important info done on server, period.

1 Like

You can also send the time from picking up the topping and putting it down. Which would mean you can detect if they are placing inhumanly (automatic topping).

There’s still further problems I forsee. For example, scores. If this is the data

local CompletePizzas = 0
local Mistakes = 0
local MaxPizzas = 30
local Speed = 3

and it’s stored on the server, another player will also be able to view this and thus scores would get interlocked with each other

Store individual players scores in a table instead of variables

Example of what I feared server side control would cause. The pizza glitches back and forth on the conveyor. So it isn’t a smooth movement.

The conveyor just has a set velocity (3, 0, 0) which makes the pizza across the screen, but ye, for some reason, causes the pizza to glitch left to right

Will the conveyor belt’s velocity be changing throughout the game for each player? E.g. player 1 gets to 15 pizzas and it speeds up to 3.5?

If the speed will be consistent throughout the whole game then you could consider creating the pizza locally on the server, with players adding their toppings to it locally. This would mean the client would locally give all the effects of adding toppings to the pizza along with firing remote events of where and when they place a topping.

I’m not sure how well this would perform, but since the pizza would be running on the server there wouldn’t be any bouncing. Just an idea you might want to explore.

Players with high network latency would be penalised, but if you’re set on making the game exploit proof then that’s probably going to have to be a compromise, you can’t account for players playing with 2 seconds of lag as exploiters can artificially create lag to their advantage.

I’d like the conveyor to change overtime.

For the time, i’ve been creating pizzas on the server. Then as player clicks and drags ingredients over, thats all client, when they release the click I create a ray to see if its on their pizza, if so, send to server to add the topping on the pizza (on the server)

This could be a rare use-case for a server using InvokeClient in a remote function?

The server invokes the client telling the player to create a pizza with an order of xyz toppings, the player then returns data when the pizza is at the end of the conveyor belt. The data would probably include the speed of the player’s local conveyor belt (so that score can be calculated) and the times and positions of the toppings that have been placed.

The server can then quickly recreate the player’s minigame using some funky maths to determine if the player was successful or not, this should theoretically replicate on the server as it was done on the client.

There is the risk of if the client never returns the value then that particular thread will hang, but when the player leaves it will error and that’ll be that. Thoughts?

Ye nah I’d rather stay well clear of InvokeClient. Can cause all manner of problems

1 Like