How to prevent hat dropping exploits?

Greetings,

I am trying to prevent hat dropping exploits in my game. Unfortunately I no longer have the screenshot but recently someone not only dropped a bunch of pirate of the Caribbean hats in my game, but also made them HUGE causing lag.

My solution is, seeing as there is only a handful of parts/models that can be added to the workspace through the gameplay or commands, to create a workspace.DescendantAdded event and check if the part is whitelisted, if not just delete it, I am not sure if this is a good option thus i am here asking others, if you’ve also had issues with this please share your experience

Thank you for your time

3 Likes

I think it’s good solution:

Put this in script in workspace/serverscriptservice

while wait(10) do --Every ten seconds
	for i,v in pairs(workspace:GetChildren()) do
		if v:IsA("Accessory") then
			v:Destroy() --It will clear all Hats/Hairs/Capes/Wings/etc. That dropped into workspace
		end
	end
end
2 Likes

i really don’t want to use a loop for this, seems very unecessary

2 Likes

Then a bit less laggy script:

workspace.ChildAdded:Connect(function(v) --Someone added hat to workspace
	if v:IsA("Accessory") then
		game.Debris:AddItem(v, 0.25) --Destroying it with debris ^_^
	end
end)
2 Likes

That won’t work, you can’t destroy a child immediately after it is parented.

Then debris it? Lemme change code

This won’t work if the hat isn’t parented directly to workspace. It can just be parented to the character. Maybe just make script that checks how many accessories are parented to character and if there’s too many, remove them.

how to hat dropping exploits even work? I tried to drop my hat via a local script in a baseplate but it didn’t replicate

I don’t know everything but i saw someone created topic about that and said that exploiters drops their hats into workspace and changing their mesh since it’s local part that inside of player. So they can load huge or laggy\messy meshes and change their size to cause lags on your server

I’m not sure how it works but I doubt exploiters can just reparent the hat somewhere else so it’s most likely parented to character, unanchored locally and somehow cloned. Or it’s just a backdoor perhaps.

Something I’ve tried before which seems to work is listening for the AncestryChanged event on each accessory in the player’s character. When it fires you simply check if the object is still a descendant of the character. If it’s not, you just delete it.

Example:

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local function OnPlayerAdded(player)
	local function OnCharacterAdded(character)
		if (not player:HasAppearanceLoaded()) then
			player.CharacterAppearanceLoaded:Wait()
		end
		local function OnAccessoryAdded(accessory)
			local function HandleParentChange(object)
				object.AncestryChanged:Connect(function()
					if (not object:IsDescendantOf(character)) then
						RunService.Heartbeat:Wait()
						object:Destroy()
					end
				end)
			end

			accessory.DescendantRemoving:Connect(function(object)
				if (not object:IsA("SpecialMesh")) then 
					return
				end

				RunService.Heartbeat:Wait()
				accessory:Destroy()
			end)

			HandleParentChange(accessory)
			for _, object in ipairs(accessory:GetDescendants()) do
				if (object:IsA("BasePart")) then
					HandleParentChange(object)
				end
			end
		end

		for _, object in pairs(character:GetChildren()) do
			if (object:IsA("Accessory")) then
				OnAccessoryAdded(object)
			end
		end

		character.ChildAdded:Connect(function(object)
			if (object:IsA("Accessory")) then
				OnAccessoryAdded(object)
			end
		end)
	end
	
	player.CharacterAdded:Connect(OnCharacterAdded)
end

Players.PlayerAdded:Connect(OnPlayerAdded)
for _, player in pairs(Players:GetPlayers()) do
	OnPlayerAdded(player)
end
1 Like

hmm, well all accesories have welds so how about checking if those welds have been destroyed?

It probably won’t replicate to server. The welds dont have to be destroyed since it’s all controlled by client anyway.

local clonedHatParent = nil -- were is it
clonedHatParent.ChildAdded:Connect(function(hat)
  if (hat:IsA('Accessory') --[[sorry if i spelled it wrong]]) then
    hat:Destroy()
    print('a hat just got removed :flushed:')
  end
end)