local positions = {}
local workspaceStuff = game.Workspace:GetDescendants()
local hackDetection = game.ReplicatedStorage:WaitForChild("ClientHackDetection")
repeat wait(1) until game:IsLoaded()
wait(20)
for _, part in pairs (workspaceStuff) do
if part:IsA("BasePart") then
positions[part] = part.CFrame
end
end
local skipWait = false
while true do
wait()
for part, originPos in pairs (positions) do
if part == nil then
-- part has been deleted!
print("Part has been deleted - set checking frequency to really low")
hackDetection:FireServer("BTools")
skipWait = true
end
if skipWait == false then
wait(0.3)
end
local succcess, message = pcall(function()
if (part.Position - originPos.p).magnitude > 10 then
skipWait = true
print("Part is in the wrong place - set checking frequency to really low")
hackDetection:FireServer("BTools")
print("Reported to server")
part.CFrame = originPos
end
end)
if succcess == false then
print(message)
end
end
end
So basically - I know this is client side but its designed to be a barrier to very basic exploits / exploiters who dont really understand how roblox or exploits work and have building tools. Problem is it seems to detect pretty much anyone on a laggy device⦠seems, obviously the people kicked very rarely admit to me that they were infact using exploits, but it seems to me that the bulk of people itās kicking for ābtoolsā are innocent.
Please try to refrain from copying my code
I assumed this was to do with loading which is why there is the āwait(20)ā and repeat wait(1) until game:IsLoaded()
Iāve managed to rule that out through this addition:
if positions[valueValue] ~= nil then
repeat
wait()
ranName = math.random(15023)
valueValue = part:GetFullName()..ranName
until positions[valueValue] == nil
end
For the FE thing: I know that but it can effect the play experience for others when players are glitching around and hovering in the air etc.
In this case you can make it a lot easier for everyone if you just look at the playerās character - this will also get rid of basic speed/jump/fly hacks instead of just building tools.
There are tools in my game and therefore I canāt just kick anyone who has tools - especially as they could very easily be named the exact same thing as the tools that I allow
(Also I am confused as to why this is giving false positives)
No, thatās not what I meant. I mean doing what you are now (checking the position of parts) except only in the character.
Thereās no need to go through the entire workspace when the only thing that replicates is the player.
Also, I recommend using the part object as the key instead of a randomly generated name. This is because dictionary[object] works, so you donāt need to waste lots of time making a random key generator.
Additionally you could also use (StartPosition-EndPosition).Magnitude, as it gets the distance between the two positions for you.
And it appears, like you said, that the issue was comparing different parts instead of a single one.
Thanks for the help in all of those areas - I think Iāll stick with comparing part positions clientside but will definitely use magnitude, the reason I wasnt is because I was originally comparing if the X axis of both was the same, then it sort of devolved into what you see there
I also set the index as the object which is much better - will update you and mark you as the solution if it works!
This is probably an issue with the exploit detection part. Try doing prints and other debugging techniques to see whatās being compared with what, etc.
Iāve marked this as right because this is definitely a suitable fix - it turns out I removed the if statement checking if the parts were anchored or not at some point while scripting it and thatās the reason. Sorry for wasting everyones time!
for _, part in pairs (workspaceStuff) do
if part:IsA("BasePart") then
positions[part] = part.CFrame
end
end
Wonāt character parts be included in this? Also:
if part == nil then
This is not the right way to detect if a part is destroyed. Check if its Parent is nil instead. Besides, this is impossible because this would mean that there is something indexed to nil in your positions table.
Lastly:
if (part.Position - originPos.p).magnitude > 10 then
Since character parts are included in a list, this would trigger if a character moves too fast (e.g. because he/she fell or glitched)
Just a tip, hackers can read your code and make it so your āhack detectionā remote does nothing. while true do end is the de facto client side cheat stopper.
You can have it be both (crashing after a delay and making sure you setup the delay before attempting to fire the remote so you donāt error if they destroy it), just make sure itās not just āhack detectionā remotes.
Check if any GUIās are added to PlayerGui that arenāt yours
Set player walk speed and jump power on a bindtorenderstep
Check if players travel massive amounts of distance with little velocity (aka, teleporting). Check with server to see if this teleport was authorized by having the server log all teleports that are SUPPOSED TO HAPPEN so no false positives.
Check if the FPS is > 70. Most exploits have an UnlockFPS option.
Check if any parts are deleted, and just like the teleport, be sure to log all intentional deletes so no false positives.
This seems pretty inefficient - why not just check every second or two and then kick them if itās been changed. Changing it every RenderStep is unnecessary lag.
Even then you should check every second and then if the walkspeed has been changed you then check every renderstepped - otherwise youāre punishing innocent players.