How to account for error in my anti-speedhack script

--Movement Validator
local LastPositions = {}
local MVLastRun = 0
local MVStep = .1
local PlayerWalkspeed = 16
game:GetService("RunService").Heartbeat:Connect(function(dt)
	if MVLastRun < MVStep then MVLastRun = MVLastRun + dt return end
	MVLastRun = 0
	for _, plr in pairs(Players:GetPlayers()) do
		local char = plr.Character
		local hrp = char and plr.Character:FindFirstChild("HumanoidRootPart")
		if char and hrp then
			if LastPositions[plr] then
				local deltaXZPlane = Vector3.new(hrp.Position.X, 0, hrp.Position.Z) 
					- Vector3.new(LastPositions[plr].X, 0, LastPositions[plr].Z)
--this line below im a little worried about
				if math.abs(deltaXZPlane.Magnitude) > (PlayerWalkspeed * MVStep + 1.5) then 
					print("SPEEDHACK DETECTED"..math.abs(deltaXZPlane.Magnitude))
					hrp.CFrame = CFrame.new(LastPositions[plr])
				end
			end
			LastPositions[plr] = hrp.Position
		end
	end
end)

Here you can see an anti-teleport/speedhack script I wrote. Its not complete yet and doesn’t account for a lot of factors, but I have a question about how latency will affect this script.

I marked the line when I determine if the players movement vector magnitude is higher than it should be. For a walkspeed of 16, the max movement should be 16 * dt so I did that initially. However in testing the server said I was hacking even though i was moveing at 16 stud/sec. I added 1.5 to the maximum movement magnitude and it started working. I think this has to do with network latency.

I have above average internet so I don’t know how a player with higher latency will be affected. Will 1.5 studs error be enough? What if I increase my walkspeed, then will the error increase? Is there a better way for me to account for latency in this system?

A common way to circumvent this is track how far in total the user has moved vs how far should be possible. Then, every 5 or so seconds, check both values, then reset them both. That way, if a user lags for a second they won’t be falsely detected.

Another way could be to make the punishment less harmful, such as teleporting them back to their previous position. However, this can cause rubber banding which can be solved with the next solution.

You could also track the number of ‘infractions’ each user has, and only punish them if they do enough in say, a minute. If the player was above that speed 2,000 times vs the 5 latency times, then finding the exploit becomes easier.

1 Like

There is no real way to prevent speed-hacking unless you use server authoritative physics (where actual character control is almost entirely server-side) or you sort-of “estimate” where the player should end up after every tick / ping request. The first example is something I myself am having trouble with solving (see Help with Lag Compensation Methods) but the second example is to do something like project a circle/sphere from the last position, with a radius of walkspeed * timeSinceLastChecked, as this an area of possibility where they theoretically would have been able to move anywhere inside of it within that amount of time. If they have moved outside of this area, you can move them back inside of it.

--loop
radius = walkSpeed*step + 0.1 --a little bit of 'give' room
dir = currentPos - lastPos
dist = dir.Magnitude
if dist > radius then --if we are further than the radius limit
    correctPos(character, lastPos + dir.Unit * radius) --project to point on sphere surface
end

As for dealing with latency, the best way would be to communicate with them using network based intervals (on their ping) like with the other post I mentioned, as this will make sure to only correct them when they responded and replicated. If they manage to disable the RF you use to communicate, they might still be able to cheat which is why I use server authoritative physics, so that if they refuse to communicate and to do so properly, nothing they do will move on to the server.