FJ's (Experimental) Character Anticheat

I created an experimental anticheat system that heavily curtails common movement cheats like speeding, teleporting, noclipping, flying, and ludicrously-fast spinning.

It does this by using a set of “heatsinks”, which quickly gain heat while a player is displaying anomalous behavior, as well as a set of assumptions, such as players only being able to jump a certain height off the ground.

Upon determining a player is cheating, it teleports that player back to where they were last time they were not acting suspicious, and then takes away physics control for a few seconds. This immediately nullifies their cheating attempt.

And best part: It runs entirely on the server, so there’s not much exploiters can do about it aside from pushing the limits!

If you’re lazy like me, you can watch this video.

Will I open-source this? Yes. But it’s my first attempt at an anticheat of its kind. I also discovered a bug that threw me off mid-development, so it’s spaghetti code. You may want to look at the techniques I listed below instead. Perhaps you can come up with a better implementation than mine.

Here’s the demo place. It’s uncopylocked if you want to play with it.

https://www.roblox.com/games/4562741079/FJs-Anticheat-Demo

Note: I’ve given an option to disable the anticheat on yourself in this demo, though you’ll have to wear the name-tag of shame (Anticheat Disabled) while it’s off. lol.

Methods

Anti-speed and Anti-teleport

image

The anti-cheat uses a Speed Heat value to gauge how fast a player is going while giving some room in case that player is a bit laggy.

Moving horizontally at normal speed does add heat, but it is cooling down fast enough to cover that speed. Moving much faster begins to heat up the gauge, and if it overheats, the player is punished.

Though as long as the player moves at normal speed, it won’t overheat.

Teleporting a distance will overheat it instantly, so it is also blocked.

Being near an object that’s moving at some velocity will increase the tolerance to cover the extra velocity, in case the player gets on top of a conveyor belt for example.

Anti-flight

image

The anti-cheat determines whether the player is standing on a solid object, and if they’re not, heats up the Flight Heat gauge. The only ways to cool this down are to fall down really fast or land on something solid again.

In addition, it has a hard jump height limit, so if a player somehow gets above that, they are instantly punished.

It makes this ground determination by firing 4 sets of raycasts, each set attempting to cover a different class of shapes and situations.

Raycasting method details
  1. Scatter raycasting.

    image

    It first fires a raycast straight down, and then it fires four other raycasts to the sides.

    This will get a ground the majority of the time, and will often get huge objects like hill-sides.

  2. Raycast straight to each nearby object’s center.

    image

    This gets somewhat weird shapes like your average ball, as well as small rods.

  3. Raycast sideways, then downwards towards each nearby object’s center.

    image

    Works well for detecting tiny cubes or really tall blocks, plus it makes detecting trusses and ladders easier.

  4. Raycast on each XYZ plane aligned with each object.

    image

    This works well for detecting thin rods that are long, no matter which end the player is closest to.

Anti-noclip

image

A raycast is made each frame between the player’s last position and the position they are at. If it hits a solid object (with some exceptions), it’ll teleport them back and take away physics control.

This is very basic though. Because it has a lot of false-positives around objects that move, I need some better method.

Anti-fling-attack

image

There’s a script going around where exploiters can spin ludicrously fast and knock other players into oblivion (or the sky). This is detected with HumanoidRootPart.RotVelocity.Magnitude, which often reaches over 1,000 when the exploit is in use.

111 Likes

I just went to the game to check this out quickly and noticed it doesn’t work with R15, do you plan to add support for it?

7 Likes

I fixed it. An error was stopping the script from working.

1 Like

You could use FindPartOnRayWithIgnoreList to detect if the part is something like a spinner or a door by doing a for loop trought a folder that contains them.

1 Like

Will there be a easy method to add exeptions for admins?

1 Like

I don’t know. I usually don’t support the common admin scripts well.

If an admin script lets you teleport around, it should work fine because the anticheat has compatibility for teleports done by server scripts.

1 Like

Okay, altough it would be nice if there was some sort of remote we could fire with a player instance so the player gets added into some sort of exeption table just to be sure an admin doesnt get kicked from the game.

Anyways i will be using it for sure in a future project as i am trash at making anti exploits😀

Thanks for sharing this.

1 Like

That sounds interesting. Can you elaborate on how you manage to tell apart a teleport done by a foreign server script from a client-sided teleport?

3 Likes

Are you OK with others using (or forking) it in their own games? Do you have a licence for this?

2 Likes

It appears as if it doesn’t recognize terrain as something valid to stand on which causes a flying false positive to occur. It should also support swimming in terrain water if that has anything to do with fixing it recognizing terrain as a platform as well.

5 Likes

There’s a quirk where position changes don’t fire a changed event when they’re done by physics or client-to-server replication, but server script changes do fire it.

-- An exception for when a server script explicitly teleports the player.
-- Exploiters are not able to trigger this from their side due to the way
-- replication works.
Torso:GetPropertyChangedSignal("CFrame"):Connect(Reset)

Knock yourself out. Though you’ll have to modify it for whatever you’re doing, since much of it is hard-coded and doesn’t anticipate every situation a game could put it through.

That’s why I didn’t put this into Community Resources. It’s not easy to use for those who are new to it. :laughing:

Oh, and yeah. It’s experimental, so it’s unstable at the moment.


The script was failing to detect the terrain within a region surrounding the player, so my fix for that was to explicitly add it to the list of things surrounding the player.

As for swimming in water, I need to figure out how to detect whether the player is inside of water. I’m hardly familiar to terrain, since I mostly use blocks for creating worlds

9 Likes

As for water, could you try creating a Region3 around the player and using Terrain:ReadVoxels to determine if they’re inside of water or not?

1 Like

I’ve figured it out.

-- Are we inside terrain water?
local tRegion = Region3.new(Torso.Position - Vector3.new(1, 1, 1), Torso.Position + Vector3.new(1, 1, 1)):ExpandToGrid(4)
local td1, td2 = workspace.Terrain:ReadVoxels(tRegion, 4)
for x, xt in ipairs(td1) do
	for y, yt in ipairs(xt) do
		for z, cell in ipairs(yt) do
			if cell == Enum.Material.Water then
				return workspace.Terrain
			end
		end
	end
end
2 Likes

If you set your humanoid’s JumpPower to anything above 50 on the server, it still thinks you’re flying despite being set on the server. This doesn’t occur for WalkSpeed though.

Also I’m not sure if this is a dev console bug or not, but the script rate appears to be rising indefinitely, and I’m not observing this rate rising behavior with any of my other scripts.

The max jump height is coded into the configuration module. This is because I am unable to precisely determine jump height from the Humanoid.JumpPower property. It has to be determined from trial-and-error.

1 Like

That’s a really cool project however what do you plan to do agaisnt the exploiter than set back their veolocity if it exceed an limit. I beleive this is how exploiter can bypass your anti cheat.

It sets their velocities to zero, so they can’t “catapult” themselves to far away places.

For no clip, small part in center of humanoid root part. If it touches something it’s not suppose to, that’s a no clipper.

That’s a bad idea. If I attach a part to the player’s character, they have physics control over it, which means they can tell the server whether or not it touched something, or detach it entirely and teleport it to a far-away location.

The server checks. The part is created on the server.