Exploiter changing Local Placement Script

Hello everyone,
I’ve been messing around with my placement system, and I removed security features from the local script and it may break the game, if the exploiter uses it. The problem is not the hacker can walk through walls, but the things that fell down on the ground through the floor are important. Is this a problem or is it just a Roblox studio bug? Here’s a link to a YouTube video: https://youtu.be/V_GxymTk2x0

The Server-Side Placement script has some security features:

  • If the part is anchored,
  • If the part has a tag to stop the placement system,
  • If the part’s new position is 31 or more studs from the player’s humanoidrootpart (31 studs because 30 studs have secure local placement script, and it sometimes triggers security features, for placing part 30.07 studs from humanoidrootpart.)

Here’s the code for the local placement script:

--!strict
local LocalPlayer : Player = game:GetService("Players").LocalPlayer
local RE : RemoteEvent = game:GetService("ReplicatedStorage"):WaitForChild("Events"):WaitForChild("PlacementSystem")
local UsingPlacementSystemRE : RemoteEvent = game:GetService("ReplicatedStorage"):WaitForChild("Events"):WaitForChild("UsingPlacementSystem")
local mouse : Mouse = LocalPlayer:GetMouse()
local character : Model = script.Parent
local humanoid : Humanoid
repeat 
	wait() 
	humanoid = character:FindFirstChildWhichIsA("Humanoid") :: Humanoid 
until humanoid
local middleOfCharacter : BasePart 
repeat
	wait()
	middleOfCharacter = humanoid.RootPart :: BasePart
until middleOfCharacter
local RunService : RunService = game:GetService("RunService")
local movePart : RBXScriptConnection
local x : number = 0
local object : BasePart
local rotation : Vector3
local ObjectParentModel : any = nil
local maxDistance : number = 30
local ListOfPropeties = {}

local function getMouseTarget() : BasePart | nil
	local blacklist = {}
	for _, player : Player in ipairs(game:GetService("Players"):GetPlayers()) do
		local Character = player.Character or player.CharacterAdded:Wait()
		table.insert(blacklist, Character)
	end

	local cursorPosition : Vector2 = game:GetService("UserInputService"):GetMouseLocation()
	local oray : Ray = game.workspace.CurrentCamera:ViewportPointToRay(cursorPosition.X, cursorPosition.Y, 0)
	local ray : Ray = Ray.new(game.Workspace.CurrentCamera.CFrame.Position,(oray.Direction * 100000))
	local FoundObject : BasePart = workspace:FindPartOnRayWithIgnoreList(ray, blacklist)

	if not FoundObject then
		print("No object Found!")
		return nil
	end

	local CharacterPosition : Vector3 = middleOfCharacter.Position
	local FoundObjectPosition : Vector3 = FoundObject.Position

	repeat
		if not ObjectParentModel then
			if not FoundObject.Parent then
				return nil
			end
			ObjectParentModel = FoundObject.Parent
		else
			ObjectParentModel = ObjectParentModel.Parent
		end
	until ObjectParentModel:IsA("Model") or ObjectParentModel:IsA("Workspace") or ObjectParentModel == nil
	if ObjectParentModel:IsA("Workspace") then ObjectParentModel = nil end	

	if ObjectParentModel then
		for _, child : Instance in ipairs(ObjectParentModel:GetDescendants()) do
			if child:IsA("BasePart") then
				ListOfPropeties[child] = {
					["CollisionGroup"] = child.CollisionGroup
				}

				child.CollisionGroup = "PlacementSystemCollisionGroup"
			end
		end
	else
		ListOfPropeties[FoundObject] = {
			["CollisionGroup"] = FoundObject.CollisionGroup
		}

		FoundObject.CollisionGroup = "PlacementSystemCollisionGroup"
	end

	UsingPlacementSystemRE:FireServer(FoundObject, true)
	return FoundObject
end

humanoid.Died:Connect(function()
	if not movePart then return end

	for ObjectInTable, tableInDictionary in pairs(ListOfPropeties) do
		if ObjectInTable:IsA("BasePart") then
			ObjectInTable.CollisionGroup = tableInDictionary.CollisionGroup
		end
	end

	ListOfPropeties = {}
	movePart:Disconnect()
end)

mouse.Button1Down:Connect(function()
	if x == 0 then
		local GMT : BasePart | nil = getMouseTarget()
		if not GMT then return end
		object = GMT
		rotation = object.Rotation

		mouse.TargetFilter = ObjectParentModel or object

		if ObjectParentModel and ObjectParentModel.PrimaryPart ~= nil then
			movePart = RunService.Heartbeat:Connect(function(deltaTime) 
				local success, result = pcall(function()
					ObjectParentModel:PivotTo(CFrame.new(
						math.floor(mouse.Hit.Position.X),
						math.floor(mouse.Hit.Position.Y + ObjectParentModel.PrimaryPart.Size.Y/2),
						math.floor(mouse.Hit.Position.Z)
						) * CFrame.fromEulerAnglesXYZ(
							math.rad(rotation.X),
							math.rad(rotation.Y),
							math.rad(rotation.Z)
						)
					)
				end)
			end)
		else
			movePart = RunService.Heartbeat:Connect(function(deltaTime) 
				local success, result = pcall(function()
					object.CFrame = (CFrame.new(
						math.floor(mouse.Hit.Position.X),
						math.floor(mouse.Hit.Position.Y + object.Size.Y/2),
						math.floor(mouse.Hit.Position.Z)
						) * CFrame.fromEulerAnglesXYZ(
							math.rad(rotation.X),
							math.rad(rotation.Y),
							math.rad(rotation.Z)
						)
					)
				end)
			end)
		end
		x = 1
	elseif x == 1 then
		if not object then return end

		local MousePosition : Vector3 = mouse.Hit.Position
		local CharacterPosition : Vector3 = middleOfCharacter.Position
		movePart:Disconnect()
		mouse.TargetFilter = nil

		for ObjectInTable, tableInDictionary in pairs(ListOfPropeties) do
			if ObjectInTable:IsA("BasePart") then
				ObjectInTable.CollisionGroup = tableInDictionary.CollisionGroup
			end
		end

		ListOfPropeties = {}

		if ObjectParentModel and ObjectParentModel.PrimaryPart ~= nil then
			RE:FireServer(Vector3.new(MousePosition.X, MousePosition.Y + ObjectParentModel.PrimaryPart.Size.Y/2, MousePosition.Z), ObjectParentModel.PrimaryPart, rotation)
		else
			RE:FireServer(Vector3.new(MousePosition.X, MousePosition.Y + object.Size.Y/2, MousePosition.Z), object, rotation)
		end
		UsingPlacementSystemRE:FireServer(object, false)
		ObjectParentModel = nil

		x = 0
	end
end)