Overview
Alright, so understanding how you want this to work, the first thing you're going to need to do is establish a listener on both the server and client for the remote event. I assume you already have something like this planned out already, but I'll just go over it again to make things clear. I'm also not sure how detailed this answer can be due to the length limit of 10k characters, so If I lack explanation of a certain topic, I apologize.
Please note
Variables I reference in my code blocks that represent objects will not be defined within the code block. This assumes you already have these values defined.
Listeners
When creating server-sided events, I usually have 3 parameters occupying the following rolls:
Player (Obviously since the first parameter is always defined as the player who fired the event)
Request (A string value that allows me to handle what instruction I want to execute)
Tuple (...) (A tuple allowing me to pass whatever, or however many arguments I want to the event)
The Request variable is going to be especially important for this situation, since you'd prefer both functions to be compatible with both machines (Client/Server). Here's an example:
Remote.OnServerEvent:connect(function(Player, Request, ...)
Request = Request:lower()
end)
Client
The client will have the same format, minus the Player argument which will be redundant when received from the server:
Remote.OnClientEvent:connect(Request, ...)
Request = Request:lower()
end)
We'll use the same request that fired the server event, to fire the client event as well. Just a nice way to keep things easy to read.
Working on the Server
Making these functions work on the server is easy, because they won't be. All the server has to do is fire client events, and what's written in the local script will handle the rest. So let's setup the server-side event with two requests. We'll just call them Global and Private.
Remote.OnServerEvent:connect(function(Player, Request, ...)
Request = Request:lower()
if Request == "global" then
Remote:FireAllClients(Request, ...)
elseif Request == "private" then
local Args = {...}
local Recipient = table.remove(Args,1)
Remote:FireClient(Recipient, Request, unpack(Args))
end
end)
This will now properly handle our client requests. Now we need to do the same for the client, so it can handle the redirected events from the server.
Working with the Client
The client will have the same Request value as given to the server, and the unpacked data will come in through the second parameter which will be a tuple.
Remote.OnClientEvent:connect(Request, ...)
Request = Request:lower()
if Request == "global" then
Module:CreateServerMessage(...)
elseif Request == "private" then
Module:CreateLocalMessage(...)
end
end)
Now both of these functions from both sides of the server can work whenever you fire the remote. If you don't want to fire the remote each time you send a message, you could make a function that does that for you, but I'm not gonna give an example of that as it's pretty self explanatory.
Questions?
Anyway, hope this helped, just let me know if you have any questions. Private messaging me, or using the Scripting Helpers chat is probably the best way to ask. If none of this answered your question, don't hesitate to ask again. I've been up for days and my mind might not grasp certain things as well.