Communicating Server -> Client -> Server

Hello.

I want to make it so i can easily get the player’s mouse position through a server script. (With S-C-S communication)

I have read some documentation but it didn’t help me still.

Thanks.

1 Like

You can create a “ping” remote event that the server fires to the specified client and a “response” remote event which the client fires back once it registers the “ping” event. Something like this:

-- Server
local mouse
local targetPlayer = -- A player variable

GetMousePing:FireClient(targetPlayer)

GetMouseResponse.OnServerEvent:Connect(function(player, mouse)
  if player == targetPlayer then
    mouse = mouse
  end
end)

-- Client
GetMousePing.OnClientEvent:Connect(function()
  GetMouseResponse:FireServer(game.Players.LocalPlayer:GetMouse())
end)

You will need to adjust this for your needs, but this is the general pattern. PS: Do not use remote functions if you are communicating S → C → S, because the player could simply leave and the server script would keep waiting for an answer, and that’s only one of the problems that you would encounter.

2 Likes

Server:

local mouse
	
	game.ReplicatedStorage.Storage.Events.getMouse:FireClient(plr)
	
	game.ReplicatedStorage.Storage.Events.getMouseResponse.OnServerEvent:Connect(function(tplr, m)
		if tplr == plr then
			mouse = m
		end
	end)

print(mouse.Hit.Position)

Client:

game.ReplicatedStorage.Storage.Events.getMouse.OnClientEvent:Connect(function()
	local m = game.Players.LocalPlayer:GetMouse()
	game.ReplicatedStorage.Storage.Events.getMouseResponse:FireServer(m)
end)

It did not work.

attempt to index nil with 'Hit'

1 Like

Yes, because you are printing the mouse immediately. Put the print after mouse = m.

1 Like

Please, don’t use RemoteEvents in order to return data from the server to the client et vice-versa. You should look into RemoteFunctions.

-- server script
local RemoteFunction = (REMOTEFUNCTION)

local pieMultipliedBy2 = RemoteFunction:InvokeClient(player, 3.14, "hello world") -- sends info to client

print(pieMultipliedBy2)
-- local script
local RemoteFunction = (REMOTEFUNCTION)

local function getInfoLol(pie, name)
    local newNumb = pie*2
    warn(name)

    return newNumb -- returns pie multiplied by 2 back to the server
end

RemoteFunction.OnClientInvoke = getInfoLol -- connects the function

By the way, if the player leaves mid-invoke, both the server and the client will error, so I’d recommend you to use pcalls in order to avoid these errors.

3 Likes

Ok but how can i use the returned value in the server script?

1 Like

You can save this data using a variable, using local.

1 Like

I am using

local mouse = game.ReplicatedStorage.Storage.Events.getMouse:InvokeClient(plr)

print(mouse.Hit.Position)

yet it still doesn’t work.

attempt to index nil with 'Hit'

Client:

local function getMouse()
	local mouse = game.Players.LocalPlayer:GetMouse()

	return mouse
end

game.ReplicatedStorage.Storage.Events.getMouse.OnClientInvoke = getMouse
1 Like

why not pack the mouse info into a table so you don’t have to try to send an object that I believe only exists on the client to the server?

game.ReplicatedStorage.Storage.Events.getMouse.OnClientInvoke = function()
return game.Players.LocalPlayer:GetMouse().Hit
end

1 Like

Can’t you just return the Hit instead of the entire mouse? I think that might work out.

1 Like

Ok, it worked this way, thanks!

This method with pcalls is not bulletproof either. Exploiters can modify the local script so it waits forever and never returns a value. That would also stop the server. You should never ever rely on the client.

I know you should never trust the client, but you can code a script that tells the server that if it waited long enough without receiving a response, it must shut it off.

Also, you can wrap the entire function inside a coroutine so it doesn’t stop the main routine.

1 Like

Yes, but at that point, it’s simpler to just use two events.

2 Likes

I disagree, using 2 RemoteEvents or even just 1 would be a lot better here. Having the client need to return in a RemoteFunction is just a bad idea, exploiters can easily abuse it.

Using a coroutine is just a waste of performance when you can easily avoid it by just using Events.