I am trying to make some sort of anti-cheat to prevent players from teleporting. What it does is takes their previous position of PrimaryPart and the current one and compares them. If the difference between them is too big, then they get kicked. And don’t worry about this system being bad, it can deal with intended player teleports.
Now what problem I encountered is how weirdly the position is being updated. I have ping of 50, and I do take in count player’s ping when calculating max possible difference.
It’s kind of hard to explain, so here is the screenshot:
...
local config = require(script:WaitForChild("Config")) --no clue why it's blue, but it doesnt seem to affect anything
local last_info = {}
local players_kicked = {}
local function setPlayerInfo(plr:Player, last:{}, deltaTime:number)
local char:Model = plr.Character
if char ~= nil and last ~= nil and char.PrimaryPart ~= nil then
local hum = char:FindFirstChildWhichIsA("Humanoid")
local maxPlayerDelta = ((10 * plr:GetNetworkPing() + hum.WalkSpeed)/1000)*(deltaTime*2)
if maxPlayerDelta < (2+(hum.WalkSpeed)/30) then
maxPlayerDelta = (2+(hum.WalkSpeed)/30)
end
local delta = (char.PrimaryPart.Position - last['position']).Magnitude
print(last['position'], "\n", char.PrimaryPart.Position)
if char.PrimaryPart then
if delta > maxPlayerDelta then
--there are some double checks
end
end
last_info[plr.Name] = {
['position'] = char.PrimaryPart.Position
}
end
end
local function refreshKickedPlayersList()
for plrName:string, kickTick:number in players_kicked do
if tick() - kickTick > 1 then
players_kicked[plrName] = nil
end
end
end
RunService.Stepped:Connect(function(t, dt)
for i, plr:Player in ipairs(Players:GetChildren()) do
local last_plr_info = last_info[plr.Name]
if last_plr_info ~= nil then
setPlayerInfo(plr, last_plr_info, dt)
else
local char = plr.Character or plr.CharacterAdded:Wait()
last_info[plr.Name] = {['position'] = char.PrimaryPart.Position}
end
end
refreshKickedPlayersList()
end)
Players.PlayerAdded:Connect(function(player)
local antiCheatProtection = Instance.new("StringValue")
antiCheatProtection.Name = "NO ANTICHEAT"
antiCheatProtection.Parent = player
Debris:AddItem(antiCheatProtection, 3)
player.CharacterAdded:Connect(function(char)
local antiCheatProtection = Instance.new("StringValue")
antiCheatProtection.Name = "NO ANTICHEAT"
antiCheatProtection.Parent = player
Debris:AddItem(antiCheatProtection, 1)
end)
end)
Players.PlayerRemoving:Connect(function(player)
last_info[player.Name] = nil
end)
There is no problem with the code itself, it is just how weirdly the position updates.
I might have a suggestion on why this happens. I forgot to tell another thing - this happens when I apply LinearVelocity to the player. So, I guess the problem is that maybe LinearVelocity somehow glitches the position and that’s why we get big delta.
I don’t know if I should post this in #bug-reports.
Why do you check this here? You have already accessed it on this line…
local delta = (char.PrimaryPart.Position - last['position']).Magnitude
If you need character why do you only wait for it in the else branch? setPlayerInfo() just assumes Character is valid?
local char = plr.Character or plr.CharacterAdded:Wait()
This is all redundant, no reference is made to antiCheatProtection except here?
Players.PlayerAdded:Connect(function(player)
local antiCheatProtection = Instance.new("StringValue")
antiCheatProtection.Name = "NO ANTICHEAT"
antiCheatProtection.Parent = player
Debris:AddItem(antiCheatProtection, 3)
player.CharacterAdded:Connect(function(char)
local antiCheatProtection = Instance.new("StringValue")
antiCheatProtection.Name = "NO ANTICHEAT"
antiCheatProtection.Parent = player
Debris:AddItem(antiCheatProtection, 1)
end)
end)
You can tidy this up with a simple check like this:
if last == nil then return end;
local char:Model = plr.Character;
local hum = char and char:FindFirstChildWhichIsA("Humanoid");
if not hum then return end;
local maxPlayerDelta = ((10 * plr:GetNetworkPing() + hum.WalkSpeed)/1000)*(deltaTime*2)
if maxPlayerDelta < (2+(hum.WalkSpeed)/30) then
maxPlayerDelta = (2+(hum.WalkSpeed)/30)
end
local delta = (char.PrimaryPart.Position - last['position']).Magnitude
print(last['position'], "\n", char.PrimaryPart.Position)
if delta > maxPlayerDelta then
--there are some double checks
end
last_info[plr.Name] = {
['position'] = char.PrimaryPart.Position
}