I need help fixing bugs with a Placement/Building System

First of all. I am not the best programmer so please tell me if there is anything i could do better or so and don’t hate on me. Also this is my first ever post here on the dev forum.

  1. What do you want to achieve? Keep it simple and clear!
    I want to achive a building/placement system like Plane Crazy.

  2. What is the issue? Include screenshots / videos if possible!
    So basicly this is a placement system that i made a the past couple days and i have had problems with it not snapping if i rotate them and i don’t know how i would make a snapping as well as a grid placement of 1 stud. There is somewhat snapping in it and it snaps on some angles but mostly when i rotate it it won’t snap correctly and moves inside the block.Check this video for a look:

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have looked up solutions on the dev forum but i have not found anything that i understand as of my knowledge.
local PosX, PosY, PosZ
local player = game.Players.LocalPlayer
local Mouse = player:GetMouse()
local UIS = game:GetService("UserInputService")
local Part = game.ReplicatedStorage.Objects.Part
local Events = game.ReplicatedStorage.Events
local Place = Events.Place
local Position = CFrame.new()
local Plot = player:FindFirstChild("Plot").Value
local Properties = game.ReplicatedStorage.Properties
local Highlight = Properties.Highlight
local NewHighlight = Highlight:Clone()
NewHighlight.Parent = Part
local NewTexture = Properties.Texture
local Plots = workspace.Plots
NewTexture:Clone()
NewTexture.Parent = Plots[tostring(Plot)].Base
local Builds = workspace.Builds
local UIS = game:GetService("UserInputService")
local Rotation = CFrame.Angles(0, 0, 0)
local RotationY = 0
local RotationX = 0
Part.Parent = game.Workspace
Part.PrimaryPart.CanCollide = false

local Parts = 0
local MaxParts = 10
local CanPlace = true

local function Snap()
	local localHit = Part.PrimaryPart.CFrame:pointToObjectSpace(Mouse.Hit.Position)

	local roundedX = math.floor(localHit.X / Part.PrimaryPart.Size.X + 0.5) * Part.PrimaryPart.Size.X
	local roundedY = math.floor(localHit.Y / Part.PrimaryPart.Size.Y + 0.5) * Part.PrimaryPart.Size.Y
	local roundedZ = math.floor(localHit.Z / Part.PrimaryPart.Size.Z + 0.5) * Part.PrimaryPart.Size.Z

	local roundedPosition = Vector3.new(roundedX, roundedY, roundedZ)

	local worldPos = Part.PrimaryPart.CFrame:pointToWorldSpace(roundedPosition)

	PosX = worldPos.X
	PosY = worldPos.Y
	PosZ = worldPos.Z

	local Params = RaycastParams.new()
	Params.FilterType = Enum.RaycastFilterType.Whitelist
	Params.FilterDescendantsInstances = {Plots[tostring(Plot)].PrimaryPart}

	local Hit = Mouse.Target
	local RaycastResult = workspace:Raycast(Hit.Position + Vector3.new(0, 100, 0), Vector3.new(0, -1000, 0), Params)

	if RaycastResult then
		local surfaceNormal = RaycastResult.Normal
		if RaycastResult.Instance == Part.PrimaryPart then
			PosX = PosX + surfaceNormal.X * Part.PrimaryPart.Size.X
			PosY = PosY + surfaceNormal.Y * Part.PrimaryPart.Size.Y
			PosZ = PosZ + surfaceNormal.Z * Part.PrimaryPart.Size.Z
		end
	end
end

local function DetectPlot()
	local Params = RaycastParams.new()
	Params.FilterType = Enum.RaycastFilterType.Whitelist
	Params.FilterDescendantsInstances = {Plots[tostring(Plot)].PrimaryPart}

	local Hit = Mouse.Target
	local RaycastResult = workspace:Raycast(Hit.Position + Vector3.new(0, 100, 0), Vector3.new(0, -1000, 0), Params)

	if RaycastResult then
		NewHighlight.OutlineColor = Color3.fromRGB(100, 255, 100)
		CanPlace = true
	else
		Part.PrimaryPart.Anchored = true
		NewHighlight.OutlineColor = Color3.fromRGB(255, 100, 100)
		CanPlace = false
		warn("Didn't hit anything!")
	end
end


local function Move()
	Snap()
	Part:SetPrimaryPartCFrame(CFrame.new(PosX, PosY, PosZ) * Rotation)
	Mouse.TargetFilter = Part
	DetectPlot()
end

Mouse.Move:Connect(Move)

Mouse.Button1Down:Connect(function()
	if CanPlace == true  then
		Position = Part.PrimaryPart.CFrame
		Place:FireServer("Part", Position)
	end
end)

UIS.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.R then
		RotationX += 90
		Rotation = CFrame.Angles(0, math.rad(RotationX), 0)
		Part.PrimaryPart.CFrame *= Rotation
	elseif Input.KeyCode == Enum.KeyCode.T then
		RotationY += 90
		Rotation = CFrame.Angles(math.rad(RotationY), 0, 0)
		Part.PrimaryPart.CFrame *= Rotation
	end
end)