Your assumption that “lower spec devices” and unreliable internet connections can in some way false-flag anticheats relies on assumption that your anticheat has no method to gracefully handle cases of abnormality. It is only logical that unless a check you’ve produced is extremely accurate, you should not ban or kick the player. Having a client-sided anticheat on top of a server-sided one would also not resolve this issue. Your idea also contradicts, you state that serversided ones can be partly false-flagged by unreliable connections (physics freezes, freezes mid-air), and although that’s true, in no way is having a client-sided anticheat as well going to resolve that. You will still be making the same checks on the server which can still yield the same false-flags.
Thanks for explaining.
in no way is having a client-sided anticheat as well going to resolve that
I was thinking more obvious changes like walkspeed being set to 100, jump power to 100 etc.
I understand what you mean but I’ve seen games get ruined by anticheats which detect false positives from normal gameplay (booga booga for example) which makes me want to reduce the possibility of them occurring. But in the process the anti exploit would probably become too forgiving.
Please don’t take this as me trying to convince you that my initial/current idea was correct but me providing my viewpoint.
I would like to comment on this:
This is a common theme I see on the devforum, that client checks are useless. I know from experience that client-side checks are not totally useless, and for the most part can perform very well alongside server side anticheats. While all client anticheats CAN be bypassed (as mine have been too), most players who come through my games don’t know how to bypass these. This is a huge window of exploiters that CAN be stopped via client sided checks. There is simply some things you just can’t determine from the server. For example, in one of my games, there’s server-side checks for speed, teleporting, flying, the usual stuff you CAN tell on the server, then on the client there is additional measures. In my game, players use classic swords to fight. There is loads upon loads of ways to cheat in sword fighting that you can’t determine on the server – resize other players hitboxes, resize your swords hitbox, teleport other players body parts to the front of your sword, change your swords grip, there is countless ways of doing these things. The only method of partially stopping this on the server is by determining the distance of the two players, and setting a cap to how far the swords can damage. This is simply not enough, and exploiters will still always have the upper hand in these fights using the aforementioned exploits. This is where the client-side comes in. With my client side check, I can use a .Changed event on the sword’s size, the sword’s grip, player hitboxes, and a good bunch more. To date, this has allowed me ban ~4,000 exploiters this year, all while doing nothing. This enables me to have a smaller moderation team, a more enjoyable experience for players, and overall everyone is happy. None of this would be possible without client-side checks, so while they can be bypassed, that doesn’t mean they aren’t worth giving at least a little bit of time into making. To review exploiter reports and ban the 4,000 players it showed me would have taken a good amount of time, far more than the two hours it took to write the client-side anticheat.
I would like to interject that your case involves a serious flaw in your game. Classic linked swords are a massive security vulnerability. This is due to their working mechanism, which revolves around the handle’s Touched event. As you should already know, even if the handling of it is serverside, the tool is under the network ownership of the client. This creates perfect grounds were clients are able to physically expand their tools or otherwise modify their positions client-side and make hits register regardless.
I don’t argue with the results of using a client-sided anticheat, you being able to ban upwards of 4,000 exploiters is great news, although I do not believe that your solution is at all effective. Instead of porting your gears / tools to methods that mitigate this massive security hole - such as with using Touched alternatives which do not rely on client physics (Raycasting, raycast-based touch implementations, Region3), you make a client-sided anticheat which hopefully prevents most of the exploiters from having any effect. This is in my opinion bad practice, as I’ve explained with work on your hit-registration methods you can completely mitigate their exploits without any exceptions. Whereas with a client anticheat you put a basic barrier in their way which a mediocre exploiter could bypass without effort and call it a day.
if hum.JumpPower ~= 50 then
game.Players.LocalPlayer:Kick(“Jump Hacks.”)
end
Just the get humanoid root part velocity and that’s it, no need for big deal.
This can be easily bypassed by removing the LocalScript.
I mean it works tho, or just add up a duplicate that when it’s removed a new one gets created and when they try again it happens again!
Is it that difficult, why would you check the distance if you’re able to see the users walkspeed on the server:
Humanoid.Running:Connect(function(speed)
print(speed)
end)
I got some false positives using this method, if you’re walking on a part that is falling your velocity will be higher as well.
“Anti exploits” similar to these can easily get bypassed with metatable hooking. Exploiters can detect and hook events connected with the humanoid by just getting the raw metatable of the game and returning nil or spoofed speed values each time the event is fired. Or, they can just disconnect the event entirely (using injectors - example code):
for i, connection in pairs(getconnections(humanoid.Running)) do
connection:Disable()
end
tl;dr - it’s that difficult
Try this:
local MaxWalkspeedAllowed = 40 --example
Humanoid.Running:Connect(function(speed) --This will keep firing every time a player moves or stop, but mostly moves
if speed > 0 then -- You can't print speed when the player is on idle.
print(speed)
if speed > MaxWalkspeedAllowed and Humanoid.Walkspeed > MaxWalkspeedAllowed then
--Kick the speed hacker.
end
end
end)
Then just dot the velocity to the humanoid root part lookvector, so the direction would be front or back.
I recommend adding +1 to walkspeed, to not get false positives, something like this:
Humanoid.Running:Connect(function(speed)
if speed > Humanoid.WalkSpeed+1 then
-- kick the speed hacker
end
end);
You may probably script this:
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
Players.PlayerAdded:Connect(function(plr)
local char = plr.Character or plr.CharacterAdded:Wait()
local Humanoid = char.Humanoid
local MaximumWalkSpeed = 16
RunService.RenderStepped:Connect(function()
if Humanoid.Walkspeed > MaximumWalkSpeed then
print("Maximum walkspeed reached.")
end
end)
end)
Humanoid.Running is replicated to server therefore it can be handled on the server. An exploiter can’t disconnect connections on the server. Still don’t recommend using Humanoid.Running since exploiters can move their character without the Humanoid.Running being activated.
There is a tween teleportation walkspeed changer. Goodluck!