Rate and critique my first anti cheat

This is my FIRST EVER ATTEMPT at a Roblox anti-cheat! It’s really bad and I didn’t spent that much time on it. I just need people to critique it so that I can improve it. It kinda works at the moment but at the same time it can definitely be bypassed; easily. Thank you :slight_smile:
I probably messed up a lot, especially with the handshakes. Yeah I tried I guess… you can criticize it as much as you need

Im gonna try to add a way to check if the distance traveled by a player is sane and also detecting no clipping

I got a lot of help from my post

I’m gonna probably not make another whole new post until I think it’s decent; well with the changes people suggested.

Anyways, here’s the code:

Client:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Handshake = ReplicatedStorage.Handshake
local GiveInfiniteCoins = ReplicatedStorage.GiveInfiniteCoins
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")

task.spawn(function()
    while task.wait(2.5) do
    Handshake:FireServer()
    end
end)

while task.wait(5) do
    if Humanoid.WalkSpeed > 16 then
    end
end

Server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Handshake = ReplicatedStorage.Handshake
local GiveInfiniteCoins = ReplicatedStorage.GiveInfiniteCoins
local Tracker = {}

local function checkStrikes(player)
    if Tracker[player.Name] and Tracker[player.Name].STRIKES == 3 then
        player:Kick("Too many strikes! Are you a hacker??")
    else
        warn("STRIKE GIVEN TO "..player.Name.."")
    end
end

game.Players.PlayerAdded:Connect(function(Player)
    Player.CharacterAdded:Connect(function(Character)
        local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
        local Humanoid = Character:WaitForChild("Humanoid")
        local leaderstats = Instance.new("Folder")
        leaderstats.Name = "leaderstats"
        leaderstats.Parent = Player
        local Coins = Instance.new("IntValue")
        Coins.Name = "Coins"
        Coins.Parent = leaderstats
        local Rank = Instance.new("IntValue")
        Rank.Name = "Rank"
        Rank.Parent = leaderstats
        Tracker[Player.Name] = {
            ["STRIKES"] = 0,
            ["PreviousPosition"] = HumanoidRootPart.Position,
            ["PreviousTime"] = os.time()
        }
        local Track = Tracker[Player.Name]
        task.spawn(function()
            while task.wait(5) do
                if os.time() - Track.PreviousTime > 10 and Player then
                    Track.STRIKES = 3
                    checkStrikes(Player)
                elseif not Player then
                    Track = nil
                end
            end
        end)
    end)
end)

GiveInfiniteCoins.OnServerEvent:Connect(function(Player)
    Tracker[Player.Name].STRIKES = 3
    checkStrikes(Player)
end)

Handshake.OnServerEvent:Connect(function(Player)
    print("Connected.")
    Tracker[Player.Name].PreviousTime = os.time()
end)
1 Like

If you need to check if a value changes, use .Changed or :GetPropertyChangedSignal.

1 Like

Is this only client sided? An exploiter can just disable the script and make their own handshake to not be detected. You should make an anticheat on the server and a client anticheat as a smaller barrier since you can’t bypass the server.

1 Like

Shoot I was gonna but I legit forgot that it only doesn’t detect Position changes unless you do it via script.

I’ll probably fix that today

Yeah it’s kinda clumpy (the original post), but there is a server script. I only put like a little time into this and most of the time I was just reviewing the stuff from my post.

Thanks for the feedback!

1 Like

Okay guys I fixed a couple of things and I’m starting a no clipping detection section. Uh yeah and I only made changes to the server sided anti cheat today, at least mostly. I added bloodbonniekingnoob1’s suggestion but other than that I added nothing else to the client sided script.

Idk if im gonna be able to work on it for a bit so yeah heres the updated code:

-- Variables

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Handshake = ReplicatedStorage.Handshake
local GiveInfiniteCoins = ReplicatedStorage.GiveInfiniteCoins
local LastCheck = os.time()
local Tracker = {}

local function checkStrikes(player)
    if Tracker[player.Name] and Tracker[player.Name].STRIKES == 3 then
        player:Kick("Too many strikes! Are you a hacker??")
    else
        warn("STRIKE GIVEN TO "..player.Name.."")
    end
end

local function checkSanity(character)
    if not character:FindFirstChild("HumanoidRootPart") and character:FindFirstChild("Humanoid").Health == 0 then -- add more checks in the future
        return true
    elseif not character:FindFirstChild("HumanoidRootPart") and character:FindFirstChild("Humanoid").Health ~= 0 then
        game.Players:GetPlayerFromCharacter(character):Kick("No HumanoidRootPart detected. Don't hack skid.")
    end
end

local function isDistanceTraveledSane(player)
    if player and workspace:FindFirstChild(player.Name) then
    local HumanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
    if checkSanity(player.Character) and Tracker[player.Name] and (HumanoidRootPart.Position.X - Tracker[player.Name].PreviousPosition.X) > 35
        or (HumanoidRootPart.Position.Z - Tracker[player.Name].PreviousPosition.Z) > 35
    then
        return false
    else
        Tracker[player.Name].PreviousPosition = HumanoidRootPart.Position
        return true
        end
    end
end

local function isNoClipping(character)
    if character and character:FindFirstChild("HumanoidRootPart") and Tracker[character.Name] and Tracker[character.Name].PreviousPosition then
        local HumanoidRootPart = character:FindFirstChild("HumanoidRootPart")
        local Ray1 = workspace:Raycast(Tracker[character.Name].PreviousPosition, CFrame.new(Tracker[character.Name].PreviousPosition).LookVector * 10)
        local Ray2 = workspace:Raycast(HumanoidRootPart.Position, -HumanoidRootPart.CFrame.LookVector * 10)
        if Ray1 and Ray2 then
            print("take")
            local Part1 = Instance.new("Part")
            local Part2 = Instance.new("Part")
            Part1.Parent = workspace
            Part2.Parent = workspace
            Part1.Position = Ray1.Position
            Part2.Position = Ray2.Position
            Part1.BrickColor = BrickColor.new("Tr. Green")
            Part2.BrickColor = BrickColor.new("Really red")
            Part1.Position = Ray1.Position
            Part2.Position = Ray2.Position
            Part1.Material = Enum.Material.Neon
            Part2.Material = Enum.Material.Neon
            Part1.Size = Vector3.new(1, 1, 1)
            Part2.Size = Vector3.new(1, 1, 1)
            Part1.Anchored = true
            Part2.Anchored = true
            return true
        else
            return false
        end
    end
end

game.Players.PlayerAdded:Connect(function(Player)
    Player.CharacterAdded:Connect(function(Character)
        local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
        local Humanoid = Character:WaitForChild("Humanoid")
        local leaderstats = Instance.new("Folder")
        leaderstats.Name = "leaderstats"
        leaderstats.Parent = Player
        local Coins = Instance.new("IntValue")
        Coins.Name = "Coins"
        Coins.Parent = leaderstats
        local Rank = Instance.new("IntValue")
        Rank.Name = "Rank"
        Rank.Parent = leaderstats
        Tracker[Player.Name] = {
            ["STRIKES"] = 0,
            ["PreviousPosition"] = HumanoidRootPart.Position,
            ["PreviousTime"] = os.time()
        }
        local Track = Tracker[Player.Name]
        Player.Chatted:Connect(function(msg)
            if msg:find("I am a hacker") or msg:find("I hate this game") then
                Track.STRIKES = 1
                checkStrikes(Player)
            end
        end)
        task.spawn(function()
            while task.wait(2.5) do
                local Result = isDistanceTraveledSane(Player)
                local noClipping = isNoClipping(Character)
                if not Result then
                    Player:Kick("Suspicious movement activity detected.")
                end
                if noClipping then
                    Player:Kick("Potential no clipping being performed.")
                end
            end
        end)
        task.spawn(function()
            while task.wait(5.5) do
                if os.time() - Track.PreviousTime > 10 and Player then
                    Track.STRIKES = 1
                    checkStrikes(Player)
                elseif not Player then
                    Track = nil
                end
            end
        end)
    end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
    if Tracker[Player.Name] then
        Tracker[Player.Name] = nil
    end
end)

GiveInfiniteCoins.OnServerEvent:Connect(function(Player)
    Tracker[Player.Name].STRIKES = 3
    checkStrikes(Player)
end)

Handshake.OnServerEvent:Connect(function(Player)
    Tracker[Player.Name].PreviousTime = os.time()
end)

It does pretty good with the non sane movement detection and stuff but im still trying to figure out the math needed for the no clipping detection because its kinda funky and doesnt work atm.

Client sided if you’re wondering (which I’m copying from the original post cuz im too lazy to hop back on studio to do):

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Handshake = ReplicatedStorage.Handshake
local GiveInfiniteCoins = ReplicatedStorage.GiveInfiniteCoins
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")

task.spawn(function()
    while task.wait(2.5) do
    Handshake:FireServer()
    end
end)

Humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
   warn("walk speed changed")
end)

UPDATES MADE:

  • Distance check [ON THE SERVER]
  • No Clip check but it doesn’t work [ON THE SERVER]
  • Checking if the player still has their HumanoidRootPart [ON THE SERVER]
  • Changed from a while loop checking if the player’s WalkSpeed is 16 [ON THE CLIENT]

a funny thing you can do with Scripts is that you can do

script.Disabled, script.Parent = true, nil

and somehow it still runs
on server scripts, this works
for client scripts, i’m not too sure ngl, but you can add a task.wait() before the code above

yes for some reason it still works, i’ve tried it myself
won’t stop the good exploiters, but it can probably confuse some incompetent skids