Okay, let me explain, so in programming there is something called ‘environments’.
An environment is basically a library of functions and variables that have been created by the code linked to the environment.
In programming,different threads have different environments, so if you define a function locally in one thread, the other threads won’t know it exists… (because it is only defined in one environment).
This is the same for roblox, in roblox, different script instances have different environments, if you define a function in one script, it won’t be accesible in other scripts, because it isn’t defined in that environment.(unless you use _G or shared)
so in your code, you have three separate environments, 2 server sided env(environment) and one client sided env.
so in your code, you defined a fn called MouseRayCast, which casts a ray and returns the result, you fire a remote to run code on the server, the server sees the instruction to call MouseRayCast and store its result in a variable.
so the server script tries to fetch the function from its environment, it sees the function is not defined and throws an error.
to fix this issue, call mouseRayCast in the environment where it is defined (aka client system script) and send the result to the server, like so:
tool.Activated:Connect(function()
--call mouse raycast, then send over the result POSITION, raycastresult itself doesn't work.
local resultPosition = MouseRayCast().Position;
remoteSystem:FireServer(resultPosition);--pass the result to the network call
end)
then in the server script, modify your function header like so;
--the player that fired the remote is the first argument passed to the handler
--then a variable amount of arguments follows, position in this case.
local function systemPP(player: Player, position: Vector3)
--your implementation.
end
Now, you might notice, it still doesn’t work…
That is because the variable tool is not defined in your server script service script.
You are using tool in the systemPP function, bu it when it tries to fetch the value of tool, it is undefined and throws an error.
This is because tool is actually defined in your client script:
local tool = script.Parent.Parent--different env + different side of server/client wall.
so to fix this issue, you can pass the tool to the server in the remote, giving the server everything it needs to complete the operation:
tool.Activated:Connect(function()
local raycastResult = MouseRaycast()
remoteSystem:FireServer(raycastResult.Position, tool)--pass tool here...
end)
Now both tool and position are defined on the server script, and it can complete the operation.
I tested the code in roblox and it works, if you click the handle on the ground it goes back in your inventory and when you equip it you get stuck in the ground, but that is because you set handle.Anchored to true, but that is a problem for another day.
Here is the full implementation including the changes:
server script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteSystem = Instance.new("RemoteEvent")
remoteSystem.Parent = ReplicatedStorage
remoteSystem.Name = "System"
local function systemPP(player: Player, result: Vector3, tool :Tool)
local cloneTool = tool.Handle:Clone()
cloneTool.Parent = game.Workspace
cloneTool.Anchored = true
cloneTool.Position = result
tool:Destroy()
end
remoteSystem.OnServerEvent:Connect(systemPP)
client script:
local remoteSystem = game.ReplicatedStorage:WaitForChild("System")
local RunService = game:GetService("RunService")--runservice goes unused...
local UserInputService = game:GetService("UserInputService")
local camera = workspace.CurrentCamera
local localPlayer = game:GetService("Players").LocalPlayer
local mouse = localPlayer:GetMouse()
local tool = script.Parent.Parent
tool.RequiresHandle = true
tool.CanBeDropped = false
local function MouseRaycast()
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {localPlayer.Character}
local raycastResult = workspace:Raycast(camera.CFrame.Position, mouse.Hit.LookVector * 1000, params)
return raycastResult
end
tool.Activated:Connect(function()
local raycastResult = MouseRaycast()
remoteSystem:FireServer(raycastResult.Position, tool)
end)
and the click detector script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("PickPut")
local handle = script.Parent.Parent
local clickDetector = handle.ClickDetector
local function onClicked(player)
local tool = Instance.new("Tool")
tool.Parent = player.Backpack
local clone = handle:Clone()
clone.Parent = tool
handle:Destroy()
end
clickDetector.MouseClick:Connect(onClicked)
There are easier ways of doing what you are trying to do.
But I won’t show them, because that is not what you asked, here is your fixed implementation, if there are any other issues, feel free to reply to this message, or if it is completely unrelated start a new post.
Hope this helps!