How to do sanity checks in this instance

I want to allow a player to mine a crystal for example. However, when they mine it, I want it to only disappear on their client side. The crystals have a HP value in them, and so when a player clicks, it takes away 1 HP. Once it hits 0, it destroys the crystal (client) and then fires an event to server, however I am unsure how to do sanity checks here (to prevent exploiters from just spamming the event

local function InputBegan(input, GPE)
	if GPE then return end
	
	if input.UserInputType ~= Enum.UserInputType.MouseButton1 and input.UserInputType ~= Enum.UserInputType.Touch then return end
	
	Crystal.HP.Value -= 1
	
	if Crystal.HP.Value <= 0 then
		Mined:FireServer()
	end
end

Exploiters can fire remotes without script access anyways, through injecting their own code. You’ll be far better off keeping a sanity check on the server.

Please read my question before writing an answer that’ll make you look foolish.

I am wanting to do sanity checks ON THE SERVER. I know exploiters can do all the stuff you mentioned. My question was how can I do sanity checks ON THE SERVER in my instance.

Please read next time

1 Like

I was referring to this part of your post, not the first portion. There’s no way to “prevent” an exploiter from spam firing a remote unless you make that remote inaccessible, rendering it redundant in the first place. In the future, I will make sure that my reply in matters of the like are abundantly clear so as to not leave you or others confused.

As far as actually performing a sanity check, seeing as how your arithmetic is being done on the client and not the server, and that no information is being passed in your call to :FireServer(), the only real way to perform a sanity check would be to keep track of the “HP” on the server so it can validate the authenticity of the call.

If you read the part I wrote before it, you’d see that I clearly understand and know that it’s impossible to prevent spamming of remote events.

I clearly stated that. My point was I don’t know how to do sanity checks for this specific use case. I know what sanity checks. I know how to implement and use them, but for this specific case I can’t think of any efficient ways.

1 Like

You can actually prevent exploiters from spamming the event using a rate limiter contrary to what @mpxrattler said using a tick limit, if it exceeds this time between remotes you just ignore them:

You can probably set the rate depending on how fast you can expect the client to mine such as if they have an iron pickaxe or diamond pickaxe depending on your game’s logic.

But it feels odd as I believe most mining games do the hp decrease logic on the server, imagine if you can edit a Humanoid’s health on the client…Yeah, I would suggest the server manage the hp of the ores like @mpxrattler suggestion even if it’s prone to network lag for simplicity in order to avoid manually coding the rate limit logic.

1 Like

I would do a magnitude check and then also use os.clock() to check when the last event was fired.

Pseudo code:

local playerFired = {}

event.OnServerEvent:Connect(function(plr)
    if os.clock() - playerFired[plr] < COOLDOWN then
        return
    end

    playerFired[plr] = os.clock()
end)

I’ll just generally say this first up; Don’t have a critical game component being handled on client side.
You seem competent enough to know that client side events can be prone to exploiting and I applaud you for knowing that, you also seem to refuse to listen to a guy who’s now responded 2 times literally explaining to you how to solve this issue.

If you still use your current method, a crystal can only be mined by one person. This is shown in this mini example:

  • Player A mines Crystal 1 and goes AFK quickly to attend to something, Crystal 1 is shown to Player A as having 50 hp
  • Player B comes up and finds Crystal 1, it’s shown to be up to 100 hp in value and begins mining away
  • Player A returns and keeps mining Crystal 1 from its last recorded 50 hp
  • Player A will end up mining Crystal 1 to completion and fire the event, meanwhile Player B is confused as to why the Crystal just disappeared at 25 hp

By storing and handling the Crystal HP on the server side, you both avoid this, and it means you can easily check either with a rate limiter or sanity check to ensure the math adds up. You could so much as run a check to say; “What was the pickaxe being use? How much damage can it do in blah many seconds? If I now run this maths, does it add up to what I’ve currently got?” and proceed from there on the server side.

This means the Crystal HP is constantly up to date, cannot be easily manipulated by exploits, and frees up client power to handle every other function it has to deal with rather than running the maths for how much HP loss the Crystal should get.

2 Likes

I don’t think it’s possible to do sanity checks this accurately if you stored it in the client.
If you wanted the crystals to be discrete for every player, you can simply use a table to keep track of the crystals health for every player, and when they want to mine the crystal, they send FireServer(crystal) request, and then on the server-side check the magnitude of the crystal and the player, and then finally decreasing the health of the crystal in that table.