Edit: It’s been a little while since I posted this but, I don’t recommend using a client sided anti cheat, if possible, use a server sided anti cheat instead; this may stop exploiters who don’t know what they’re doing but, an experienced exploiter could easily bypass this through the use of metamethods and functions hooks.
Just another project I was working on because I was bored
Sulphur is a client sided anti cheat module I’ve been working for a little while now and I thought I would open source it since I haven’t come across an anti cheat on The Devforum yet.
It was created to prevent client sided exploits such as teleportation.
How to get Sulphur
How to use Sulphur
Sulphur was designed with security in mind, it uses an authentication key which is generated to authenticate whether a function was called from a script which has been authorized or else, the called function won’t run.
Authenticating a script
The module should contain a Child called Scripts which is an IntValue, change the value of Scripts to the number of scripts which will use Sulphur (I recommend placing scripts which will use Sulphur in ReplicatedFirst since we don’t want an exploiter to be given a key & I don’t recommend placing the module in a folder which will be explained later).
local AuthenticationKey = Sulphur:Authenticate()
This will return a key which will be used to authenticate requests, each script will be provided a unique key
Checking if a script has been removed
We don’t want an exploiter to disable scripts which use Sulphur; using the module would be futile as a result.
We will be using our Authentication Key to verify that we are calling the function through an authorized script
The table will contain the locations which we want to check(e.g game.ReplicatedFirst)
We will place 2 scripts in the same directory which will both check if a script has been removed, we will use 2 scripts because, if we were using 1 script, it could be easily removed without triggering the check
I recommend that you don’t use a folder since folders can be destroyed and the script won’t be able to check if the folder which it’s in has been removed, instead, place the scripts in a location which can’t be removed such as ReplicatedFirst or StarterPlayerScripts
Checking if a script has been disabled
As well as checking if a script has been removed, we will also check if a script has been disabled, since scripts can be disabled by exploiters which would make using an anticheat module useless.
We’ll call this from 2 scripts, if we had one script checking if a script has become disabled, it could be easily disabled without triggering the check
Checking if a player has changed their speed
We can check if a player has changed their speed, we could check on the server but bear in mind, this is a clientsided anticheat and it’s made to reduce strain on the server (I might work on a server sided anticheat in the future)
If a player attempts to change their speed, it will be changed back to the speed allowed by the developer, if you want to change a players speed, there is a function that can be used which will be explained later
Checking if a player has teleported
You can check if a player has teleported by measuring the total distance they have moved by within a given time. We can use a really simple equation to measure the maximum distance the player can travel within a given time (Distance = Speed * Time).
First, we find the players position then we wait (I’ve used RenderStepped:Wait()) since it seems to be the most accurate. Before we wait, we will store the current time in a local variable then, after the wait, we will find the players position again, then will calculate the total time taken.
We will work out the magnitude by creating a vector using Vector2; we will also subtract the players walk speed multiplied by the time taken to account for the time taken by the wait().
We will calculate the maximum distance possible by multiplying it by 0.1 which is an upper bound to decrease the frequency of / (prevent) false positives.
Once we have done all the calculations, we can check if the magnitude is greater than the maximum distance possible, if so, we will move the player back to where they were before and the player will be given a strike, if the number of strikes exceeds 10 (feel free to modify this value or delete the function), the player will teleported back to the game preventing them from attaching them selves to players. (We’re assuming that they must be trying to attach them selves to a player if they’re trying to teleport more than 10 times)
Note: This is only for the axis X and Z since a player can jump from a building which would trigger a false positive, there is a check for the Y axis which will be explained later.
As long as you don’t change the players speed to something extremely high such as 1000, there shouldn’t be any false positives
Checking if a player is attempting to fly
I won’t go into much detail about how this function works but, it checks whether a descendant has been added to the players character; if the object added is in the check, the player will be teleported back to the game (preventing them from flying).
Checking if a player has changed their JumpPower
This is really similar to how the Walkspeed check is done, so I won’t go into how it works.
Checking if a player has added a humanoid
Players can remove their humanoids and insert another humanoid preventing them from dying, to prevent this, we can check if a humanoid has been added to the players character, if so, the player will be teleported back into the game.
Checking if a player has changed their HipHeight
When a player changes their HipHeight, it’ll appear as if they’re floating and may give them some advantage in some games, to prevent this, you can check if a players HipHeight changes, if it does, we will change it back
Preventing players from teleporting in the Y axis
The reason I didn’t want to include this in the anti teleportation function mentioned before is because players can jump from high altitudes and trigger false positives, so I created a separate check for the Y axis, this checks if a players Y position has increased by a large amount but it doesn’t check if a players Y position has decreased by a large amount (I’m not certain whether I will update this in the future). This only works with a constant jump power of 50 currently since there are many factors that affect how high up a player can jump such as the gravity of the Workspace, etc. I don’t recommend using this if you’re going to not use the default values of JumpPower and Gravity.
- First, the players position is saved to a local variable, then there is a wait of 0.1 second and then the players Y position is saved to a local variable
- After the values have been saved, they are ready to be compared, if the second position (position saved after the wait) - 10 is greater than the original position, the player is teleported back to their position before the wait. There are no strikes since there is a higher chance of false positives.
Changing a players speed without triggering any checks
While I was making this, I had trouble changing the players speed without triggering any checks; I didn’t want to use global variables since they could be changed by an exploiter, instead, I made it so the module would change the players speed for you without triggering any checks.
- The players speed is constantly checked for any changes and then compared against a local variable, when you change the players speed using the function mentioned before, a Boolean which we will call Bool1 is set to true, then the script waits until a Boolean which indicates whether the anti teleportation loop has ended or is currently running, we will call this Boolean Bool2, there is a wait() loop in the anti teleportation loop which is triggered when the Bool1 is true, once Bool2 is true, the characters speed is changed then Bool1 is set to false and the anti teleportation loop continues since Bool1 is no longer true.
Note: The argument “Speed” is an integer
This is intended for games without an anticheat against simple exploits, if you can make your own anticheat, I recommend that you do so instead of using this module
Test out some features of the module:
Example Place (if you’re not sure how to use the module yet):
-Sulphur Example - Roblox
If you’re wondering why players aren’t kicked or banned, it’s because I’m currently aware that Roblox doesn’t like it when you kick/ban players but I do plan on implementing a ban list in the future.
If you find any bugs, vulnerabilities or have any suggestions, feel free to contact me on the Devforum