I’ll update it to use coroutine later but what’s wrong with wait()?
_G can overlap, I know but how else would I let every other script to get that information?
Please tell me how to improve it.
I’ll update it to use coroutine later but what’s wrong with wait()?
_G can overlap, I know but how else would I let every other script to get that information?
Please tell me how to improve it.
However, the code being exploitable is still an issue and this code doesn’t work against competent cheaters.
I’m pretty confident about it being unbypassable despite it being a remote event.
If you could, make changes to the local script in a way that will bypass it.
The issue is, you seem to not understand how much power exploiters actually have and i made a thread about it some time ago, ill link it for you if you wish to read about it.
Here’s a simple breakdown of how exploiters spoof namecalls, this should make it easier to understand why your code is ineffective against them:
I know how they work, I know what they can do. This one though uses data from the client but it can’t be modified unless the client wants to be unable to play.
I think it’s not bypassable by itself.
It will only have some small bypasses (i.e slightly increased speed) when it’s made into a game.
If i were to manipulate the localscript to send the spawnposition only, then toggle some speed exploits, would it detect me?
There is a normal magnitude check at the end of the server script, you wouldn’t be able to move 20 studs away from the saved location.
I also told in the post that they should use the _G.Location to get players location and do things with that instead of the normal .Character.HumanoidRootPart.Position things
Essentially, you can’t play the game.
Not to mention you’re moving but not sending to the servers the needed data, the anti cheat could ban you instead of tping you back
Many exploiters use delete tool and F3X, so add a whitelist script that bans everyone who isn’t white listed with f3x
this is very simple to bypass, you disable the local script and then just fire the remote yourself with spoofed details that pass the servers criteria. you could also just hook onto the localscript right before it fires and spoof the player location, many ways to bypass the localscript check atleast.
This is a VERY bad way to make an anti-cheat. I made one a while ago that is very basic and may not be the most consistent, but does the job since you would get kicked for the time without the server receiving anything if you were laggy enough to trigger a false positive. If I were an exploiter I could literally just make a script that deleted your client side portion and replace it with a script that just pings with the position that the character was in when my script first started.
What? To detect an exploit like giving yourself tools requires a client side script that can be bypassed by using DEX (which protects itself from detection) to delete the script.
what if I want to increase the character’s speed by a power up? then?
This wouldn’t work, there’s a part of the server script that checks your character’s actual position.
Guys, it’s simple, if you’re using remote events anywhere in your anti cheat, it’s bypassable. Remote events, can be intercepted, manipulated, changed, stopped entirely, etc. Yeah this would kick them if they outright stopped it, but an exploiter can literally just fake the positional data of their character that’s being sent over the remote event. In fact all they’d have to do is change this line from this
updatecharacter:FireServer(deltatime, Player.Character.PrimaryPart.Position)
to this
updatecharacter:FireServer(deltatime, Vector3.new(0, 0, 0))
Now let’s look at the logic in check:
pos
= (0, 0, 0)
local old = _G.Locations[p.Name]
= (0, 0, 0)
((old-pos)*Vector3.new(1,0,1)).Magnitude
= 0
distance > dt*p.Character.Humanoid.WalkSpeed*1.25
= false
, distance is 0, the remote says they didn’t move at all
local a = pos - old
= (0, 0, 0)
local direction = a.Unit*a.Magnitude
= (0, 0, 0)
local raycastResult = workspace:Raycast(old, direction, raycastParams)
= nil
because the length of the ray is 0. Therefore the noclip check passes as well because a ray of length 0 doesn’t actually exist and will always return nil.
With both checks passing, _G.Locations[p.Name]
is set to (0, 0, 0)
and the process repeats
There’s no way to do these types of things in a non-bypassable way utilizing remote events.
for i,v in pairs(_G.Locations) do
if (player[i].Character.PrimaryPart.Position - v).Magnitude > 20 then -- Change 20 to your allowed distance
player[i].Character.PrimaryPart.Position = v --go ban them instead?
end
end
At the end of the server script, there is this, it blocks the player from moving away from saved location. There is definitely a way to just instant ban you as you’re replicating your movement on the server but not firing the remote.
Furthermore, in the post, I told people to use _G.Locations to get character position instead of doing .Character.PrimaryPart.Position to do stuff. If developers do this, it is pointless for the exploiters to do that.
I have some experience with exploits and I can say this won’t work. InfYeild comes with a remote spy. It can read and modify remotes. For instance it can block remotes with stop remotes from firing. And with some code you can make a speed modifier. It will just block the script and fire every now and then. It is not the easiest but it could work.
This would work, but there is a loophole in which the creator can make. Even if you do manage to do it, running a sanity check on the server could work. Hell, just not even using the remote could work. You could then kill two birds with one stone.
The remote exist so that ping doesn’t matter. Normally developers do checks purely on the server side which is affected by ping so the allowed distance is usually very high. While with this method, the allowed distance is very low as ping doesn’t matter, it limits more cheats than a normal check on the server would do.
i.e, autofarming. Exploiters usually use tween (with like 2x the normal speed) to somewhat bypass the check on the server as the allowed distance is very high. With this, they can only use tween with the base speed (or slightly higher) to do so.
Stopping the remote from firing and then fire with their own settings once in a while is indeed very hard and pretty pointless. The magnitude check at the end prevents them from moving 20 studs away from the position + they have to take account in the anti noclip, firing it while behind a wall will cause the anti noclip to fire.
And again, I have say this to 2 people already, you’re moving on the server but not sending the data needed. There is definitely a way to detect that and ban you instantly.
While I personally wouldn’t say this is the best ever anticheat, this is a super cool start to a project and I’m super happy to see you employing a lot of concepts that many people miss. Ultimately there are still many flaws with how you designed this and how its ended up, but its clear that you have the understanding to polish it up.
It’s clear you spent a lot of time on this, and it’s clear you had fun, and it really reminds me of some of my favorite of my own projects in the past. I can imagine this being something you would like to be able to look back to in the future.
You employ server side physics validation, which, in my opinion is awesome, and I am super happy to see another project doing this. You clearly have an understanding of why you are doing what you are, and you clearly have an understanding of why those things are effective.
Here’s a few areas I could come up with where either the code in general or the design behind the anticheat can be improved, and hopefully some ways you can solve some of them:
dt
. One I noticed you haven’t addressed that looks like it should work would be passing NaN
as a dt
value, which eliminates the checks in your lower loop since comparisons on NaN
always return false.pos
, it would cause an error to be thrown, but only after the player’s time data would be updated, allowing the exploiter to bypass checks by breaking them entirely.task.wait
in your client loop, but, you don’t do that in your server loop (which you definitely should). I assume that’s just an oversight. You should also avoid _G
partly because its bad practice, and partly because its less performant when you could just use a couple local. Since os.clock
now exists, you should use it over tick
. tick
is better for things where you want to display time to the user, or if you wanted to base certain things by their timezone. os.clock
is more precise & future-proof (well, if you don’t consider your code breaking in millions of years future-proof) and will be consistent when comparing the server and client (1 second is always 1 second, regardless of timezones and leap time)You can fix 2, and 3 by typechecking data received from remotes, as well as ensuring that dt == dt
to avoid abusing NaN, but, I would personally not recommend relying on remotes at all (though there are definitely caveats to that as you brought up in an above reply)
4 and 5 are generally just organization and learning good styling and general programming habits, which, I’m pretty sure took me like 5 years to figure out even a bit of, especially with the resources I was learning from being strictly low quality free models. Personally I’m still improving in both areas yet I’m still mentioning it, so yeah haha.
Here’s an old GitHub project of mine which was an anticheat much like this one which I wrote for a game (neither of which unfortunately are likely to go much further). I’ve archived it at this point. You might find some useful stuff in it (you can also see a the issues and pull requests people made and get an idea of how the project changed while I was still developing it)
I don’t care how it or its code gets used, and I don’t even mind if people blatantly steal it at this point, so, if you find anything of value in it, I’d be really glad