So, here’s what the problem is. I have a sword with a part named Handle and inside that handle is the server script. All the damage is done through the server script when the handle hits a player and stuff. However, exploiters have been able to change the handle size and hit people for miles. I thought it was not possible because they only changed the handle size locally, and not on the server and the damage is done through the server script. Why is this so? Is there a way to fix this?
When you equip a Tool it is welded onto the Player Character’s Hand. At that point the network ownership of the Tool is given to the Player. Because of this, the Touched event is also fired based on if the Handle is touched locally.
Fixing this is a bit complicated due to latency issues. But as an example you can have a localscript checking if the handle size is changed locally and kicking people, preventing this from happening in the first place. When doing damage, you could also calculate the distance of the Tool’s handle to the touched part to see if it’d be realistic for them to touch.
Thanks for the reply! I tried kicking if the handle’s size isn’t what I set and check for distance. However, they are still getting past that with meta table hooking. Is there a way I can set ownership to the server?
It is possible with a simple
Handle:SetNetworkOwnership(nil)
I don’t recommend this though since it’ll quickly revert back unless the entire character’s ownership is set to the server. At which point the game becomes very unresponsive. Other methods of handling this is to create a seperate copy of the handle not welded to anything and on the server setting its CFrame to match to what the server sees the Tool’s handle to be. This also has the drawback of not being as responsive, but worth giving a try.
Alright, thanks! I will try them both, but you’re saying setting the handle’s ownership to the server will automatically revert it back?
In general I don’t recommend it because it is still welded to the character. Having a Server calculated object interacting with Client calculated object causes issues
So, there isn’t really a good way to fix this? Hm, is there any way to prevent meta table hooking?
No. The client has complete control over their own computer. You could use something doesn’t have the NetworkOwnership set to the client and try to align its position and orientation with the tool without constraints, then using its .Touched event instead of the tool’s, but that might be more effort than it’s worth.
Make sure that the hits actually make sense before dealing damage. For instance, the player should not be able to hit from 100 studs away, so make sure the distance between the Player’s character and the character that was hit isn’t a super big difference.
In Code (Because I am terrible at explaining lol)
local Hitbox = script.Parent.Handle
Hitbox.Touched:Connect(function(hitpart)
local humanoid = hitpart.Parent:FindFirstChild("Humanoid")
if humanoid then
if (humanoid.Parent.HumanoidRootPart.Position - script.Parent.Parent.HumanoidRootPart.Position).Magnitude < 10 then
humanoid:TakeDamage(10)
end
end
end)
Of course, the player can also exploit their position near the player then kill them, but for now this should work.
On the server-side, you could make it so that you check whether or not the hitbox has changed when the .Touched
event fires.
It would look something like this:
local Players = game:GetService("Players")
local Tool = script.Parent
local Handle = Tool.Handle
local Player
if workspace:IsAncestorOf(Tool.Parent) then
Player = Players:GetPlayerFromCharacter(Tool.Parent)
else
Player = script.Parent.Parent
end
-- Just a safety precaution, haven't tested if they can be parented to something
-- than the Backpack and the character on server-side.
if not Player then
Tool:Destroy()
end
local OriginalSize = Handle.Size
local function OnTouched(Hit)
local Character = Hit.Parent
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid", true)
if Humanoid and Players:GetPlayerFromCharacter(Character) then
if OriginalSize ~= Handle.Size then
-- Do what action you want regarding the player here, you have the
-- player holding the tool
Player:Kick("ok")
return
end
Humanoid:TakeDamage(10)
end
end
Handle.Touched:Connect(OnTouched)
Properties like size do not replicate to the server.
Size changes don’t replicate, use @TotallyTrustful 's solution instead.
@TotallyTrustful @NachtHemd
How come they are able to change the hitbox of the part, and it actually works on the server-side?
Server-side .Touched
is server-side meaning, say a client sets the part size to 512, 512, 512
and the position of the part is 0, 0, 0
, that wouldn’t replicate to the server, and therefore .Touched
would not fire any parts on the server-side.
I can confirm however that size changes do not replicate.
The Player has control over the physics of the object, meaning it has full control over .Touched
calls, and the server will receive
them. However, properties of the part that do not relate to physics will not replicate (ex. Size or Color)
Some exploits also have a built in API that allows them to fire RBXScriptSignals without the need for changing size either.
I can confirm that .Touched
is replicated to the server-side.
That’s a pretty bad thing, might make a feature request about that sometime in the near future.
Your solution probably works the best, but the code could be made a bit cleaner?
Also after reading through the replies, the OP has stated these following things:
They just do something called meta table hooking and when ever the script looks for the size it gives the fake one.
That’s exactly what I’m trying to prevent. No good way to do that I guess.
As far as I know this is intended behavior. Connecting the Touched event creates a TouchTransmitter instance named TouchInterest, which is used to send data to the server, much like RemoteEvents.
Also worth to mention that a TouchInterest will not replicate the event if neither of the touching parts are network owned by the player. Then again, characters are replicated in a really weird undefined way.