Make auto gun raycast serversided

so i did do a patrt of it, now teher is two raycasts, one for client and one for server, i just took the position, size and the color to the server and made a part, how would i make the whole thing serversided?
client script:

local Debris = game:GetService("Debris")

local LaserGun = script.Parent
local Tip = LaserGun:WaitForChild("Tip")
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Player = game.Players.LocalPlayer
local Character = Player.Character

local GunDamage = 30
equipped = false
shooting = false
local connection

LaserGun.Parent.Equipped:Connect(function(Mouse)
	equipped = true
	connection = Mouse.Button1Down:Connect(function()
		shooting = true
		while shooting and equipped do
			local Laser = Ray.new(Tip.CFrame.p, (Mouse.Hit.p - Tip.CFrame.p).unit * 300)
			local HitPart, HitPosition = game.Workspace:FindPartOnRay(Laser, Character, false, true)
			LaserGun.Position += LaserGun.CFrame.RightVector * 0.1;
			local LaserBeam = Instance.new("Part", game.Workspace)
			LaserBeam.BrickColor = BrickColor.new("New Yeller")
			LaserBeam.FormFactor = "Custom"
			LaserBeam.Material = "Plastic"
			LaserBeam.Transparency = 0.25
			LaserBeam.Anchored = true
			LaserBeam.CanCollide = false
			
			local LaserDistance = (Tip.CFrame.p - HitPosition).Magnitude
			LaserBeam.Size = Vector3.new(0.3, 0.3, LaserDistance)
			LaserBeam.CFrame = CFrame.new(Tip.CFrame.p, HitPosition) * CFrame.new(0, 0, -LaserDistance/2)
			wait(0.1)
			LaserGun.Position += LaserGun.CFrame.RightVector * -0.1;
			Debris:AddItem(LaserBeam, 0.1)
			ray:FireServer(LaserBeam.Size,LaserBeam.CFrame,LaserBeam.BrickColor)
			if HitPart then
				local HitHumanoid = HitPart.Parent:FindFirstChild("Humanoid")
				if not HitHumanoid then
					HitHumanoid = HitPart.Parent.Parent:FindFirstChild("Humanoid")

				end

				if HitHumanoid and HitHumanoid ~= script.Parent.Parent.Parent.Humanoid then
					HitHumanoid:TakeDamage(GunDamage)
				end
			end
			wait(0.1)
		end
	end)
end)
LaserGun.Parent.Unequipped:Connect(function(Mouse)
	equipped = false
end)

Player.Mouse.Button1Up:Connect(function()
	shooting = false
	connection:Disconnect() 
end)

server script:

wait()
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")

ray.OnServerEvent:Connect(function(plr,size,position,color)
	local LaserBeam = Instance.new("Part", game.Workspace)
	LaserBeam.Anchored = true
	LaserBeam.Size = size
	LaserBeam.CFrame = position
	LaserBeam.BrickColor = color
	LaserBeam.Transparency = 0.5
	wait(0.1)
	LaserBeam:Destroy()
end)

I don’t see a raycast on the server side. Ultimately, you need to do a raycast on the server, where the client sends the server the laser tool’s position as well as the mouse hit position, and the server creates its own ray and performs its own :FindPartOnRay from that ray. Creating a client-sided laser beam from a client-sided raycast is fine, except the local client will see two laser beams, one from the client and one eventually created by the server. Either you need to not create the beam on the client (not good for immediate feedback) or you need to have the server FireAllClients() with a different RemoteEvent that tells everyone to draw a laser beam whilst also passing the player who shot. That way, the shooting player can compare it’s player name to the shooting player name from the FireAllClients() event, and it won’t create a laser beam if the two player names are equal.

The “if Hitpart” section of the code needs to be on the server. It won’t even work on the client side, as the client doesn’t have the ability to invoke the TakeDamage() method on Humanoids other than the local humanoid.

so i just pass the hitpart and the hitposition to the server and copy the rest?

1 Like

Yes so in your local script you would pass all the params of your RayCast through a remote event.

(WARNING VERY VERY LOOSE EXAMPLE DO NOT COPY)

RayCastEvent:FireServer(RayCastPos,RayCastDirection)

and then you would receive this in the server script and use those params to cast a ray.

Remember that a cheating client could send a bogus position. It would be ideal to only pass the part the client thinks it hit. Then the server can do its own ray cast based on where it knows the player’s tool position to be in the direction of the part the client claims it hit. If that part is indeed hit, then you know the client isn’t performing a “shoot-through-walls” hack, for example.

Of course, I just wanted my example to be very simple and easy to understand to get him started with raycasting.

1 Like

hmm i worked on sorting the stuff and did this:

local Debris = game:GetService("Debris")

local LaserGun = script.Parent
local Tip = LaserGun:WaitForChild("Tip")
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Player = game.Players.LocalPlayer
local Character = Player.Character

local GunDamage = 30
equipped = false
shooting = false
local connection
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
LaserGun.Parent.Equipped:Connect(function(Mouse)
	equipped = true
	connection = Mouse.Button1Down:Connect(function()
		shooting = true
		while shooting and equipped do
			LaserGun.Position += LaserGun.CFrame.RightVector * 0.1;
			ray:FireServer(script.Parent.Tip.CFrame.Position, Mouse.Hit.Position)
			wait(0.1)
			LaserGun.Position += LaserGun.CFrame.RightVector * -0.1;
		end
	end)
end)
LaserGun.Parent.Unequipped:Connect(function(Mouse)
	equipped = false
end)

Player.Mouse.Button1Up:Connect(function()
	shooting = false
	connection:Disconnect() 
end)

now i just gotta do the server side

1 Like

Nice work so far keep it up! I’d like to offer a little bit of advice to clean up your variables and separate it a bit more from that beefy function of yours.

Did you intend to define “ray” twice?

1 Like

oh ye oops lemme delete that rn, i am trying to modify a youtuber’s script, it works…ish, the bullet hole is stacking on top of eachother, trying to make an if statement for that rn

local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")



ray.OnServerEvent:Connect(function(Player, FromP, ToP)
	local RayCast = Ray.new(FromP,(ToP-FromP).unit*100)
	local Part,Position,Normal = game.Workspace:FindPartOnRay(RayCast,Player.Character, false,true)
	local Dist = (ToP-FromP).magnitude
	if not Dist then Dist = 300 end
	local Lazer = Instance.new("Part")
	Lazer.Parent = game.Workspace
	Lazer.Anchored = true
	Lazer.CanCollide = false
	Lazer.Size = Vector3.new(0.5,0.5,Dist)
	Lazer.CFrame = CFrame.new(FromP,Position)*CFrame.new(0,0,-Dist/2)
	local Hole = game.ReplicatedStorage.Hole:Clone()
	Hole.Parent = Part.Parent
	if ToP.Name ~= Hole then
	Hole.Position = ToP
	Hole.CFrame = CFrame.new(Hole.Position, Hole.Position+Normal)
	local Weld = Instance.new("Weld")
	Weld.Part0 = Part
	Weld.Part1 = Hole
	Weld.C0 = Part.CFrame:Inverse()
	Weld.C1 = Hole.CFrame:Inverse()
	Weld.Parent = Hole
		game.Debris:AddItem(Lazer,0.2)
		end
	if Part and Part.Parent:FindFirstChild("Humanoid") then
		Part.Parent.Humanoid:TakeDamage(30)
	end
	game.Debris:AddItem(Hole,10)
end)

yeah it fires unstoppably for some reason, i suppose ill give up the ray part for now and try work on the gun and bullet part

k im done sorting stuff heres the scripts

wait()
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Debris = game:GetService("Debris")
ray.OnServerEvent:Connect(function(plr,HitPart,HitPosition,Tip)
	local LaserBeam = Instance.new("Part", game.Workspace)
	LaserBeam.BrickColor = BrickColor.new("New Yeller")
	LaserBeam.FormFactor = "Custom"
	LaserBeam.Material = "Plastic"
	LaserBeam.Transparency = 0
	LaserBeam.Anchored = true
	LaserBeam.CanCollide = false
	local LaserDistance = (Tip.CFrame.p - HitPosition).Magnitude
	LaserBeam.Size = Vector3.new(0.3, 0.3, LaserDistance)
	LaserBeam.CFrame = CFrame.new(Tip.CFrame.p, HitPosition) * CFrame.new(0, 0, -LaserDistance/2)
	wait(0.1)
	Debris:AddItem(LaserBeam, 0.1)
end)

that was server now client

local Debris = game:GetService("Debris")

local LaserGun = script.Parent
local Tip = LaserGun:WaitForChild("Tip")
local ray = game.ReplicatedStorage.Toolevents:WaitForChild("Ray")
local Player = game.Players.LocalPlayer
local Character = Player.Character

local GunDamage = 30
equipped = false
shooting = false
local connection

LaserGun.Parent.Equipped:Connect(function(Mouse)
	equipped = true
	connection = Mouse.Button1Down:Connect(function()
		shooting = true
		while shooting and equipped do
			local Laser = Ray.new(Tip.CFrame.p, (Mouse.Hit.p - Tip.CFrame.p).unit * 300)
			local HitPart, HitPosition = game.Workspace:FindPartOnRay(Laser, Character, false, true)
			LaserGun.Position += LaserGun.CFrame.RightVector * 0.1;
			wait(0.1)
			LaserGun.Position += LaserGun.CFrame.RightVector * -0.1;
			ray:FireServer(HitPart,HitPosition,Tip)
			wait(0.1)
		end
	end)
end)
LaserGun.Parent.Unequipped:Connect(function(Mouse)
	equipped = false
end)

Player.Mouse.Button1Up:Connect(function()
	shooting = false
	connection:Disconnect() 
end)

please tell me if i did something wrong with the moving

If I’m going to be honest with you, you’ll learn much quicker if you actually script it yourself. Everything you need is on the devforum.

1 Like

well i kinda learn while editing, i have to know what each part does for me to change it, or else i can’t edit at all, im just bad at putting stuff together so i learn by breaking apart other people’s finished product to fit my needs

3 Likes

You haven’t done the raycast on the server side yet. That is critical to do, or else the client can change what it sends on the “Ray” event to whatever it wants, and the server has no idea if it should damage the HitPart’s humanoid or not.

Remember that the localscripts you make can be completely changed to anything that a hacker wants it to be. The only thing hackers can’t change are server-side scripts. It’s ok for the client to do its own ray cast, but the server must double-check and validate what the client sends.

For example, the client is sending the “Tip” part to the server, and the server blindly believes that it has received the tip of the shooter’s gun. A hacker won’t send the tip of their gun. They will change the localscript to send a part that’s right next to the HitPart on the player they want to damage. The server will then blindly cast a ray from the fake Tip part to the HitPart, see that it’s close and isn’t blocked by anything, and it will incorrectly damage an innocent player that could be 5000 studs away from the hacker.

how would i validate? do i make each tool tip differant or something?

You get the plr object on the server side when the Ray event fires. Use that player object to get its character object, then the tool object from the character, then the tip from the tool.

--do this in the server script inside the ray server event
local serverTip = plr.Character.Tool.Tip  --I don't know what your Tool is named here
local shooterTipPosition = serverTip.Position
local serverLaserRay = Ray.new(shooterTipPosition, (HitPosition - shooterTipPosition).unit * 300)
local serverHitPart, serverHitPosition = game.Workspace:FindPartOnRay(serverLaserRay, plr.Character, false, true)
if HitPart ~= serverHitPart then
    print("Either " , plr.Name, " is a cheater or a big lagger!")
    return
end