I want to carry a variable (v) from the client to the server to the client. The reason for this is because v in it’s original localscript is within a condition. I can transmit it to the server just fine, but it breaks when I try and carry it to the client. This is my script:
am:FireServer() --Is within a condition in a localscript
am.OnServerEvent:Connect(function(player, v) --Legacy script in SSS
print("fired")
am:FireClient(player, v)
end)
am.OnClientEvent:Connect(function(player, v) --Back to the original localscript that am:FireServer() is in
print("fired")
local mark = Instance.new("Highlight", Character)
mark.Name = "Mark"
mark.FillTransparency = 1
mark.OutlineColor = Color3.new(1, 1, 0)
wait(10)
mark:Destroy()
Use a RemoteFunction instead, unlike a RemoteEvent which will only send Data from Client > Server and Vice Versa, a RemoteFunction will send it from Client > Server > Client and vice versa, as it allows you to return Data.
Hey, so I did what you said and it still does’nt work. I get the error: “OnClientInvoke is a callback member of RemoteFunction; you can only set the callback value, get is not available”. I already reverted all FireClients to InvokeClients and OnClientEvents to OnClientInvokes. Is there something else I need to do?
I can’t really do that though, since the variable I want to transmit, v, is within a condition, and can’t be defined by a function. Unless, of course, I’m stupid. This is my code:
local am = rs:WaitForChild("applymark")
for i, v in pairs(workspace:GetPartsInPart(x)) do
if v.Parent:FindFirstChild("Humanoid") and v.Parent ~= Character and v.Parent:FindFirstChild("Hit"..Player.Name) == nil then
am:InvokeServer(v)
print("fired")
v.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
local x = Instance.new("IntValue", v.Parent)
x.Name = "Hit"..Player.Name
game.Debris:AddItem(x, 1)
damageevent1:FireServer(v)
end
end
for i, v in pairs(workspace:GetPartsInPart(x)) do
if v.Parent:FindFirstChild("Humanoid") and v.Parent ~= Character and v.Parent:FindFirstChild("Hit"..Player.Name) == nil then
function applymark(v)
return v
end
am.OnClientInvoke = applymark
print("fired")
v.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
local x = Instance.new("IntValue", v.Parent)
x.Name = "Hit"..Player.Name
game.Debris:AddItem(x, 1)
damageevent1:FireServer(v)
end
end
and after that, how do i actually invoke the server. is it just applymark:InvokeServer?
function applymark(v)
return v
end
for i, v in pairs(workspace:GetPartsInPart(x)) do
if v.Parent:FindFirstChild("Humanoid") and v.Parent ~= Character and v.Parent:FindFirstChild("Hit"..Player.Name) == nil then
applymark(v)
print("fired")
v.Parent:FindFirstChild("Humanoid"):TakeDamage(10)
local x = Instance.new("IntValue", v.Parent)
x.Name = "Hit"..Player.Name
game.Debris:AddItem(x, 1)
damageevent1:FireServer(v)
end
end
Simple, when firing a remote event, you do not have to get it from the client, the server will only fire the variable, try removing the “player” from the client, and just put your variable.
When using FireClient(Player, Info), you would need to mention the player, as your only sending the info through one client, however while using FireAllClients(info), You would not need to mention the player, as your firing this to all the players/clients.
Now from the client’s side, the server will not send the player, this is because the client can easily get the player from using local Player = game.Players.LocalPlayer.
So to answer your question, just remove the player from the client side while using am.OnClientEvent:Connect(function(player, v), Instead write am.OnClientEvent:Connect(function(v)
Don’t use remotefunctions because if they error its events could hang indefinitely
Here is some code from a network module i wrote that makes remoteevents work as a 2-way remote:
function Network.Invoke(Remote: string, ...: any): ...any
assert(IsServer == false, "Invoke can only be called on client")
local Connection, Data, Response
Connection = Network.Connect(Remote, function(...) Data = {...} Response = true; end)
Network.FireServer(Remote, ...)
local E = 0
repeat E += task.wait() until (Data ~= nil) or (E > Network.InvokeTimeout) or (Response == true)
if Connection then Connection:Disconnect() end
if (Data == nil) and (E > Network.InvokeTimeout) then return nil end
return unpack(Data)
end
As a standalone function it would look something like:
---server script
local RemoteEvent = nil :: RemoteEvent -- remoteevent
RemoteEvent.OnServerEvent:Connect(function(Player, FishString)
local DataFromServer = {Fish = FishString}
local s, e = pcall(function()
-- do stuff here
task.wait(1)
DataFromServer.Origin = "Bass_ProShop_Pyramid"
end)
if not s then warn(e) end
print(DataFromServer)
RemoteEvent:FireClient(Player, DataFromServer)
end)
---client script
local InvokeTimeout = 2
local RemoteEvent = nil :: RemoteEvent -- remoteevent
local function Invoke(Remote: RemoteEvent, ...: any): ...any
local Connection, Data, Response
Connection = Remote.OnClientEvent:Connect(function(...)
Data = {...}
Response = true
end)
Remote:FireServer(...)
local E = 0
repeat E += task.wait() until (Data ~= nil) or (E > InvokeTimeout) or (Response == true)
if Connection then Connection:Disconnect() end
if (Data == nil) and (E > InvokeTimeout) then return nil end
return unpack(Data)
end
local DataFromServer = Invoke(RemoteEvent, "i love fishing")
print(DataFromServer) --[[
Fish = "i love fishing";
Origin = "Bass_ProShop_Pyramid"
]]