RemoteSignal
A remote signal in layman's terms is simply an object which dispatches data to a client (who can listen to this data through a client remote signal) and listens to data dispatched to itself by a client (through a client remote signal).
Types
DefaultRemoteSignalConfig
interface
DefaultRemoteSignalConfig {
automaticArgumentSerializationAndDeserializationEnabled:
true
globalRateLimit:
0
useUnreliableRemoteEvent:
false
}
DefaultRemoteSignalMiddleware
interface
DefaultRemoteSignalMiddleware {
serverEvent:
{
}
}
RemoteSignal
RemoteSignalConfig
interface
RemoteSignalConfig {
useUnreliableRemoteEvent:
boolean
--
determines whether or not the remote signal will use UnreliableRemoteEvent
or RemoteEvent
internally.
automaticArgumentSerializationAndDeserializationEnabled:
boolean
--
determines whether or not values sent to clients by the remote signal be internally serialized/deserialized or not.
globalRateLimit:
number
--
(in seconds) will serve as the global rate limit for all players firing to this RemoteSignal.
}
-
automaticArgumentSerializationAndDeserializationEnabled
->true
- Arguments and values sent across the network by the remote signal will be automatically serialized and deserialized respectively, with the help of an internal library, i.e serializerUtil.
Serialization and deserialization limitations
While the serializer utility used to accomplish this supports a variety of data types, do keep in mind that not all data types can be supported on the go for serialization and deserialization - check the above hyperlink to the serializer utility on how many data types it supports.
::::
**See the type of the value sent to the client by the remote signal, being `TweenInfo` on the client**:
```lua
-- Server
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local testNetwork = network.Server.new("TestNetwork")
local remoteSignal = network.Server.RemoteSignal.new()
testNetwork:append("remoteSignal", remoteSignal)
testNetwork:dispatch(Workspace)
remoteSignal:fireClient(Players:GetPlayers()[1] or Players.PlayerAdded:Wait())
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
testNetwork.remoteSignal:connect(function(value)
print(typeof(value)) --> "TweenInfo"
end)
```
-
automaticArgumentSerializationAndDeserializationEnabled
->false
- Arguments and values sent across the network by the remote signal will not be internally serialized and deserialized. Using the same example as above:
See the type of the value sent to the client by the remote signal, being
TweenInfo
on the client:-- Server local Workspace = game:GetService("Workspace") local Players = game:GetService("Players") local testNetwork = network.Server.new("TestNetwork") local remoteSignal = network.Server.RemoteSignal.new() testNetwork:append("remoteSignal", remoteSignal) testNetwork:dispatch(Workspace) remoteSignal:fireClient(Players:GetPlayers()[1] or Players.PlayerAdded:Wait()) -- Client local Workspace = game:GetService("Workspace") local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect() testNetwork.remoteSignal:connect(function(value) print(typeof(value)) --> "table" end)
RemoteSignalMiddleware
interface
RemoteSignalMiddleware {
}
Yielding in middleware callbacks is not allowed
Middleware callbacks aren't allowed to yield. If they do so, their thread will be closed via coroutine.close and an error will be outputted in the console.
Yielding, (especially in network-related code) results in weird bugs and behavior which can be hard to track down!
serverEvent
Callbacks in serverEvent
are called whenever the client fires off the remote signal.
The first argument passed to each callback is a reference to the remote signal itself, which is followed by the client itself, which is followed by an array of arguments fired by the client.
local serverEventCallbacks = {
function (remoteSignal, client: Player, arguments)
print(RemoteSignal.is(remoteSignal)) --> true
print(client:IsA("Player")) --> true
print(typeof(arguments)) --> "table"
end
}
---
More control
- If any of the callbacks return an explicit false value, then the remote signal will not be fired. For e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testNetwork = network.Server.new("TestNetwork")
local testRemoteSignal = network.Server.RemoteSignal.new({
serverEvent = {function() return false end}
})
testRemoteSignal:connect(function()
print("Fired") --> never prints
end)
testNetwork:append("signal", testRemoteSignal)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace)
print(testNetwork.signal:fireServer())
- Additionally, you can modify the
arguments
table before it is passed to the connected callback, for e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testNetwork = network.Server.new("TestNetwork")
local testRemoteSignal = network.Server.RemoteSignal.new({
serverEvent = {
function(_, arguments)
arguments[2] = 5
arguments[3] = "test"
end
}
})
testRemoteSignal:connect(function(client, a, b)
print(a, b) --> 5, "test" (a and b ought to be 1 and 24 respectively, but they were modified through the middleware)
end)
testNetwork:append("signal", testRemoteSignal)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("Test", Workspace):expect()
print(testNetwork.signal:fireServer(1, 24))
Functions
new
Creates and returns a new remote signal.
- If the 2nd parameter
middleware
is not specified, then it will default to DefaultRemoteSignalMiddleware instead. - If the 3rd parameter
remoteSignalConfig
is not specified, then it will default to DefaultRemoteSignalConfig instead.
is
RemoteSignal.
is
(
self:
any
) →
boolean
Returns a boolean indicating if self
is a remote signal or not.
connect
RemoteSignal instance
Connects callback
to the remote signal so that it is called whenever the client
fires the remote signal. Additionally, callback
will be passed all the arguments sent
by the client.
-- Server
remoteSignal:connect(function(client, a, b)
print(a + b) --> 3
end)
-- Client
clientRemoteSignal:fireServer(1, 2)
Possible Rate Limit
It is possible that the client firing to this remote signal is intercepted by a rate-limit, either due to the global rate limit imposed on this remote signal for all players, or a specific-rate limit imposed for this client.
local remoteSignal = RemoteSignal.new(nil, 10) -- global rate limit of 10 seconds
-- Server
remoteSignal:connect(function()
print("Fired")
end)
--> "Fired"
-- Only printed once!
-- Client
for _ = 1, 5 do
clientRemoteSignal:fireServer()
end
If you do not desire this behavior, you can do the following:
- Set a specific rate limit for the client through RemoteSignal:setClientSpecificRateLimit or RemoteSignal:setClientSpecificRateLimits, to
0
. - Not impose a global rate limit to the remote signal (See RemoteSignalConfig for more info).
once
RemoteSignal instance
Works almost exactly the same as RemoteSignal:connect, except the
connection returned is disconnected immediately upon callback
being called.
wait
RemoteSignal instanceRemoteSignal:
wait
(
) →
...any
Connects callback
to the remote signal so that it is called whenever the remote signal
is fired off by the client successfully. Additionally, callback
will be passed all the arguments sent
by the client.
-- Server
remoteSignal:connect(function(client, a, b)
print(a + b) --> 3
end)
-- Client
clientRemoteSignal:fireServer(1, 2)
wait
RemoteSignal instanceRemoteSignal:
wait
(
) →
...any
Yields the current thread until the remote signal is successfully fired off by the client. The yielded thread is resumed once the client fires some data to the server successfully, with the arguments sent by the client.
-- Server
local client, a, b = remoteSignal:wait()
print(a + b) --> 3
-- Client
clientRemoteSignal:fireServer(1, 2)
setGlobalRateLimit
RemoteSignal instanceRemoteSignal:
setGlobalRateLimit
(
globalRateLimit:
number
) →
(
)
Sets the given remote signal's global rate limit - clients firing to this remote signal will be ignored
if the time (in seconds) between their last fire and the new fire is less than globalRateLimit
.
-- Server
remoteSignal:setGlobalRateLimit(10) -- 10 seconds
remoteSignal:Connect(function(client)
print("2")
end)
--> "2"
-- Client
for _ = 1, 100 do
clientRemoteSignal:Fire() -- Only 1 fire call will be respected by the server, rest will be ignored!
end
NOTE
Clients who have a specific rate limit set through RemoteSignal:setClientSpecificRateLimit will not be affected by this global rate limit.
globalRateLimit
RemoteSignal instanceRemoteSignal:
globalRateLimit
(
) →
number
Returns the remote signal's global rate limit. Defaults to 0
.
clientSpecificRateLimit
RemoteSignal instanceReturns the given client
's rate liimt set specifically on them.
setClientSpecificRateLimit
RemoteSignal instanceSets a specific rate limit for the given client.
NOTE
This specific rate limit set for this client will be removed once the client leaves the game.
setClientSpecificRateLimits
RemoteSignal instanceWrapper for RemoteSignal:setClientSpecificRateLimit for an array of clients.
removeClientSpecificRateLimit
RemoteSignal instanceRemoves the specific rate limit set for the given client through RemoteSignal:setClientSpecificRateLimit.
Global Rate Limit
If the remote signal has a global rate limit set (see RemoteSignal.new's second parameter), then the given client will now be subject to that global rate limit.
If you do not desire this behavior and want the rate limit imposation completely lifted for the client,
you should set a specific rate limit of 0
for the given client (through RemoteSignal:setClientSpecificRateLimit).
removeClientSpecificRateLimits
RemoteSignal instanceWrapper for RemoteSignal:removeClientSpecificRateLimit for an array of clients.
fireClient
RemoteSignal instanceFires the given arguments to client
.
fireAllClients
RemoteSignal instanceRemoteSignal:
fireAllClients
(
...:
any
) →
(
)
Calls RemoteSignal:fireClient for every player in the game, passing in the given arguments along.
fireClients
RemoteSignal instance
Iterates through clients
and calls RemoteSignal:fireClient for each client,
passing in the given arguments along.
fireAllClientsExcept
RemoteSignal instance
Calls RemoteSignal:fireClient for every player in the game, except for client
,
passing in the given arguments along.
destroy
RemoteSignal instanceRemoteSignal:
destroy
(
) →
(
)
Destroys the remote signal and renders it unusable.