A really helpful person helped me make a function that allows people to throw things.
He used a remote function and it went like this:
Local script:
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local rfunc = script.Parent:WaitForChild('RemoteFunction')
rfunc.OnClientInvoke = function() -- not safe
return mouse.Hit.Position
end
Normal script:
local tool = script.Parent
local part = tool.Handle
local rfunc = tool:WaitForChild('RemoteFunction')
local ratio = 2
tool.Activated:Connect(function()
local player = game.Players:GetPlayerFromCharacter(tool.Parent)
local mousepos = rfunc:InvokeClient(player)
local direction = (mousepos - tool.Parent.PrimaryPart.Position)
local force = direction * ratio + Vector3.new(0, game.Workspace.Gravity * 0.5 / ratio, 0)
tool.Parent = workspace
part.AssemblyLinearVelocity = force
end)
It works amazingly well, but I’ve been trying to find a way to make it work while removing the invoke client. (although it doesnt really matter for the purpose that it is serving, I want to learn how to do this anyway)
I’ve watched multiple videos on remote events, functions, etc but no matter what I do i cant really get it to work.
I’ve been trying this for around one hour so but I cant and im really stumped
You can’t get the mouse’s worldspace position from a server script so at the very least you’ll need to use a RemoteEvent/RemoteFunction instance in order to facilitate communication between the server and the client, are you intending to use a RemoteEvent instance instead?
--CLIENT
local players = game:GetService("Players")
local player = players.LocalPlayer
local mouse = player:GetMouse()
local tool = script.Parent
local remote = tool:WaitForChild("RemoteEvent")
remote.OnClientEvent:Connect(function()
remote:FireServer(mouse.Hit.Position)
end)
--SERVER
local players = game:GetService("Players")
local tool = script.Parent
local handle = tool.Handle
local remote = tool.RemoteEvent
tool.Activated:Connect(function()
if not tool.Enabled then return end
tool.Enabled = false
local character = tool.Parent
local player = players:GetPlayerFromCharacter(character)
if player then
remote:FireClient(player)
end
end)
remote.OnServerEvent:Connect(function(player, mousePosition)
local direction = (mousePosition - handle.Position)
local force = direction * 2 + Vector3.new(0, workspace.Gravity / 4, 0)
handle.AssemblyLinearVelocity = force
tool.Parent = workspace
end)
This is terribly incorrect, and InvokeClient() is unsafe no matter what. Also, here’s the fixed version of @Forummer’s code.
Server: (client is fine)
local players = game:GetService("Players")
local tool = script.Parent
local handle = tool.Handle
local remote = tool.RemoteEvent
tool.Activated:Connect(function()
if not tool.Enabled then return end
tool.Enabled = false
local character = tool.Parent
local player = players:GetPlayerFromCharacter(character)
if player then
remote:FireClient(player)
end
end)
remote.OnServerEvent:Connect(function(Player, mousePosition)
local direction = (mousePosition - handle.Position)
local force = direction * 2 + Vector3.new(0, workspace.Gravity / 4, 0)
handle.AssemblyLinearVelocity = force
tool.Parent = workspace
end)
edit: The “player” argument (1st argument) of the OnServerEvent connection wasn’t set; just for clarification.
Both local & server scripts were previously incorrect on my end, when I wrote the code I initially used FireAllClients() which doesn’t require the player argument on the firing or listening side, I later switched to FireClient() but forgot to include the player argument.
Just to let you know, you’d be better off using InvokeClient() for this while utilising the pcall() global.
--CLIENT
local players = game:GetService("Players")
local player = players.LocalPlayer
local mouse = player:GetMouse()
local tool = script.Parent
local remote = tool:WaitForChild("RemoteEvent")
remote.OnClientInvoke = function()
return mouse.Hit.Position
end
--SERVER
local players = game:GetService("Players")
local tool = script.Parent
local handle = tool.Handle
local remote = tool.RemoteEvent
tool.Activated:Connect(function()
if not tool.Enabled then return end
tool.Enabled = false
local character = tool.Parent
local player = players:GetPlayerFromCharacter(character)
if player then
local success, result = pcall(function()
return remote:InvokeClient(player)
end)
task.delay(10, function()
if (result == nil) then
player:Kick("Disconnected.")
end
end)
if success then
if result then
local direction = (result - handle.Position)
local force = direction * 2 + Vector3.new(0, workspace.Gravity / 4, 0)
handle.AssemblyLinearVelocity = force
tool.Parent = workspace
end
else
warn(result)
end
end
end)
InvokeClient() can be made safe by kicking the player if they attempt to infinitely yield the invocation.
Thank you for linking this topic, I have a question, would wrapping the method you showed in a coroutine as well be useful? Just so other players aren’t affected if someone tries to yield and don’t have to wait the 10 seconds if a yielder is caught?