Anti-Cheat Basics
Understanding anti-cheat systems and false positives.
Concepts
Never accept results from the client
A modified client can trigger any server event with any arguments. Let the client ask for an action and have the server read every value that matters (position, inventory, job, cooldown) itself. Do not accept coordinates, prices, amounts or targets from the client and only range-check them.
-- server.lua: the client only says "I am at checkpoint N"
local CHECKPOINTS = {
vector3(215.8, -810.1, 30.7),
vector3(-1037.6, -2737.6, 20.2),
}
RegisterNetEvent('myresource:claimCheckpoint', function(index)
local src = source
if type(index) ~= 'number' or index % 1 ~= 0 then return end
local target = CHECKPOINTS[index]
if not target then return end
local ped = GetPlayerPed(src)
if ped == 0 then return end
-- The server's view of the position, not a client-supplied value.
if #(GetEntityCoords(ped) - target) > 5.0 then
print(('[myresource] %s claimed checkpoint %d from too far away'):format(src, index))
return
end
-- Grant the reward here, using server-side state only.
end)The server position is the last state the client synced, so it can lag slightly behind. Use a tolerance that fits your gameplay and log rejections instead of punishing them immediately. See secure events for the full checklist.
Rate limiting
Keep the limit per player. A single shared timestamp lets one player lock everyone else out of the feature.
local lastAction = {}
RegisterNetEvent('myresource:action', function()
local src = source
local now = GetGameTimer()
if lastAction[src] and now - lastAction[src] < 1000 then
return -- too fast
end
lastAction[src] = now
-- Process action
end)
-- Server IDs are reused after a disconnect (immediately on Enhanced), so
-- forget per-player state when the player leaves.
AddEventHandler('playerDropped', function()
lastAction[source] = nil
end)Block client-side entity creation
With OneSync, clients can create networked entities unless you lock that down.
Use sv_entityLockdown or per-bucket SetRoutingBucketEntityLockdownMode and
create entities from server code instead. See OneSync.
False Positives
Common causes:
- Network lag
- Script bugs
- Legitimate edge cases
Best Practices
- Log suspicious activity
- Review before banning
- Provide appeals process
- Monitor false positive rate