RemoteProperty
A remote property in layman's terms is simply an object which can store some global value as well as values specific to players.
Types
DefaultRemotePropertyConfig
interface
DefaultRemotePropertyConfig {
automaticArgumentSerializationAndDeserializationEnabled:
true
}
DefaultRemotePropertyMiddleware
interface
DefaultRemotePropertyMiddleware {
clientSet:
{
...
}
clientGet:
{
}
}
By default, clientSet
contains a function which always returns [RejectClientSetRequest], in
order to reject the client's request of setting a value for themselves in the remote property, as this is a
security risk, if by default, this behavior is allowed. Additionally, a warn is also produced in the output
to let you know of this.
So in order to allow clients to request the server to set their value, then you must define a middleware where clientSet
contains
at least 1 function, for e.g;
local remoteProperty = RemoteProperty.new({
clientSet = {
function(_, _, valueFromClient)
return valueFromClient
end
}
})
RemotePropertyConfig
interface
RemotePropertyConfig {
automaticArgumentSerializationAndDeserializationEnabled:
boolean
--
determines whether or not values sent to clients by the remote signal be internally serialized/deserialized or not.
}
automaticArgumentSerializationAndDeserializationEnabled
->true
- Arguments and values sent across the network by the remote property 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 of the remote property being `TweenInfo` on the client**:
```lua
-- Server
local Workspace = game:GetService("Workspace")
local testNetwork = network.Server.new("TestNetwork")
local remoteProperty = network.Server.RemoteProperty.new(TweenInfo.new())
testNetwork:append("remoteProperty", remoteProperty)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(typeof(testNetwork.remoteProperty:get())) --> "TweenInfo"
```
-
automaticArgumentSerializationAndDeserializationEnabled
->false
- Arguments and values sent across the network will not be internally serialized and deserialized. Using the same example as above:
See the type of the value of the remote property being
table
on the client instead ofTweenInfo
:-- Server local Workspace = game:GetService("Workspace") local testNetwork = network.Server.new("TestNetwork") local remoteProperty = network.Server.RemoteProperty.new(TweenInfo.new()) testNetwork:append("remoteProperty", remoteProperty) testNetwork:dispatch(Workspace) -- Client local Workspace = game:GetService("Workspace") local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect() print(typeof(testNetwork.remoteProperty:get())) --> "table"
RemoteProperty
RemoteProperty
Observer
type
Observer =
(
newValue:
T
,
oldValue:
T?
)
→
(
)
RemotePropertyMiddleware
interface
RemotePropertyMiddleware {
}
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!
clientSet
Callbacks in clientSet
are called whenever the client tries to set the value of the remote property
for themselves specifically.
The first argument passed to each callback is a reference to the remote property itself, followed by the client object and the value the client is trying to set.
local clientSetCallbacks = {
function (remoteProperty, client, value)
print(RemoteProperty.is(remoteProperty)) --> true
print(client:IsA("Player")) --> true
end
}
---
More control
A clientSet
callback can return a non-nil value, which will then be set as the value for the client in the remote property.
This is useful in cases where you want to have more control over what values the client can set for themseves in the remote
property.
For e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testRemoteProperty = network.Server.RemoteProperty.new(50, {
clientSet = {function() return "rickrolled" end}
})
local testNetwork = network.Server.new("TestNetwork")
testNetwork:append("property", testRemoteProperty)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
testNetwork.property:set(1)
print(testNetwork.property.onUpdate:Wait()) --> "rickrolled" (This ought to print 1, but our middleware returned a custom value!)
You can also return [RejectClientSetRequest] from a clientSet
middleware callback, in order to reject the client's
request of setting a value for themselves in the remote property.
Additionally, if more than 1 callback returns a value, then all those returned values will be packed into an array and then sent back to the client. This is by design - as it isn't ideal to disregard all returned values for just 1.
For e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testRemoteProperty = network.Server.RemoteProperty.new(50, {
clientSet = {
function() return "rickrolled" end,
function() return "oof" end,
function() return "hello" end
}
})
local testNetwork = network.Server.new("TestNetwork")
testNetwork:append("property", testRemoteProperty)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
testNetwork.property:set(1)
print(testNetwork.property.onUpdate:Wait()) --> {"oofed", "rickrolled", "hello"}
If any of the clientSet
middleware callbacks return [RejectClientSetRequest], then the client's
request of setting a value for themselves in the remote property, will be rejected.
clientGet
Callbacks in clientGet
are called whenever the client tries to get the value of the remote property.
The first argument passed to each callback is a reference to the remote property itself, which is followed by the client object.
local clientGetCallbacks = {
function (remoteProperty, client)
print(client:IsA("Player")) --> true
end
}
---
More control
A callback can return a non-nil value, which will then be returned to the client. This is useful in cases where you want to have more control over what values the client can retrieve from the remote property.
For e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testRemoteProperty = network.Server.RemoteProperty.new(5000, {
clientGet = {function() return "rickrolled" end}
})
local testNetwork = network.Server.new("TestNetwork")
testNetwork:append("property", testRemoteProperty)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.property:get()) --> "rickrolled" (This ought to print 5000, but our middleware returned a custom value!)
Additionally, if more than 1 callback returns a value, then all those returned values will be packed into an array and then sent back to the client. This is by design - as it isn't ideal to disregard all returned values for just 1.
For e.g:
-- Server
local Workspace = game:GetService("Workspace")
local testRemoteProperty = network.Server.RemoteProperty.new(50, {
clientGet = {
function() return "rickrolled" end,
function() return "oof" end,
function() return "hello" end
}
})
local testNetwork = network.Server.new("TestNetwork")
testNetwork:append("property", testRemoteProperty)
testNetwork:dispatch(Workspace)
-- Client
local Workspace = game:GetService("Workspace")
local testNetwork = network.client.fromParent("TestNetwork", Workspace):expect()
print(testNetwork.property:get()) --> {"oofed", "rickrolled", "hello"}
Properties
RejectClientSetRequest
Read onlyRemoteProperty.RejectClientSetRequest:
"RejectClientSetRequest"
A marker that can be passed from a clientSet
middleware callback, to reject a client's request of setting
some value (for themselves in the remote property).
onUpdate
Read onlySignalRemoteProperty InstanceRemoteProperty.onUpdate:
Signal
<
newValue:
T,
oldValue:
T?
>
A signal which is fired whenever the value of the remote property is set to a new one. The signal is only passed the new value as the only argument.
clientValueOnUpdate
Read onlySignalRemoteProperty Instance
A signal which is fired whenever the value
of player
specifically in the remote property is set to a new one. The signal is passed the player
as the first argument, and the new specific value of player
set in the remote property, as the second argument.
Functions
new
Creates and returns a new remote property with the value of initialValue
.
-
If the 2nd parameter
middleware
is not specified, then it will default to DefaultRemotePropertyMiddleware instead. -
If the 3rd parameter
remotePropertyConfig
is not specified, then it will default to DefaultRemotePropertyConfig instead.
is
RemoteProperty.
is
(
self:
any
) →
boolean
Returns a boolean indicating if self
is a remote property or not.
get
RemoteProperty instanceRemoteProperty:
get
(
) →
T
Returns a shallow copy of the current value set for the remote property.
valuePromise
RemoteProperty instanceRemoteProperty:
valuePromise
(
valuePredicate:
(
T:
any
,
oldValue:
T?
)
→
boolean
) →
Promise
<
T
>
Returns a promise which is resolved with a non-nil value of the remote property, given
that valuePredicate
is not passed as an argument.
remoteProperty:valuePromise():andThen(function(value)
print(value)
end)
valuePredicate
can also be passed, which allows you to filter out values. If it returns
exactly true
, only then will the promise resolve with the new value.
remoteProperty:valuePromise(function(newValue, oldValue)
return newValue == 10 and oldValue == 1
end):andThen(function(value)
print(value)
end)
remoteProperty:set(1)
remoteProperty:set(10)
--> 10
setRateLimitForClientSettingValue
RemoteProperty instanceRate limits the given client setting their own value by rateLimit
seconds.
NOTE
This specific rate limit set for this client will be removed once the client leaves the game.
-- Server
remoteProperty:setRateLimitForClientSettingValue(client, 30) -- 30 seconds
-- Client
clientRemoteProperty.onUpdate:Connect(function(newValue)
print(newValue)
end)
-- Spam the setting of value for the client, so we ought for the value of the
-- client stored in the remote property (finally) to be `100`, but instead
-- it will be `1`, as subsequent calls after the first one will be ignored
-- due to the rate limit imposed.
for index = 1, 100 do
clientRemoteProperty:set(index)
end
--> 1
setForClients
RemoteProperty instanceCalls RemoteProperty:setForClient for all clients in clients
.
setForClient
RemoteProperty instance
Sets the value of the remote property for client
specifically, to value
. This client
will now no longer be receiving updates of the value of the remote property, and thus will only
be receiving updates of their own specific value set in the remote property.
NOTE
RemoteProperty:removeForClient will be called for the given client whenever they leave the game, so that this value is cleared out for the player, and thus this helps prevent memory leaks.
Precaution!
-
Setting the value for
client
tonil
will not remove the client's value - call RemoteProperty:removeForClient to do that. -
This method will throw an error if you attempt to set a value for the client who are not present anymore in the server (i.e not a descendant of Players) - this is done to avoid memory leaks.
removeForClient
RemoteProperty instance
Removes the value stored for client
specifically in the remote property. This client will
now be informed of the current value of the remote property and will now no longer be
receiving updates of their specific value (that was previously set in the remote property, as
it has been removed), instead the client will start receiving updates of the value of the remote
property itself.
removeForClients
RemoteProperty instanceIterates through clients
and calls RemoteProperty:removeForClient for each client.
clientHasValueSet
RemoteProperty instance
Returns a boolean indicating if there is a specific value stored for client
in the remote property.
clientValue
RemoteProperty instanceReturns a shallow copy of value stored specifically for client
in the remote property.
clientValuePromise
RemoteProperty instanceRemoteProperty:
clientValuePromise
(
valuePredicate:
(
newValue:
T
,
oldValue:
T?
)
→
boolean
) →
Promise
<
any
>
Returns a promise which is resolved with a non-nil value of the value stored for the client in the remote property.
remoteProperty:clientValuePromise(client):andThen(function(value)
print(value)
end)
valuePredicate
(an optional predicate), allows you to filter out values:
remoteProperty:clientValuePromise(client, function(newValue, oldValue)
print(newValue, oldValue)
return oldValue == 1
end):andThen(function(value)
print(value)
end)
remoteProperty:setForClient(client, 1)
remoteProperty:setForClient(client, 2)
-- Output:
-- 1, nil
-- 2, 1
-- 2
set
RemoteProperty instanceRemoteProperty:
set
(
value:
T
) →
(
)
Sets the value of the remote property to value
. Clients who have a specific value set
will not be informed of this new value of this remote property.
clientValueOnUpdateSignalForClient
RemoteProperty instanceReturns a signal that is fired whenever a value is set for the client, or the client's specific value is updated in the remote property (through RemoteProperty:setForClient).
remoteProperty:clientValueOnUpdateSignalForClient(somePlayer):Connect(function(newValue, oldValue)
print(newValue, oldValue)
end)
remoteProperty:setForClient(somePlayer, 1)
--> 1, nil
observeClientValue
RemoteProperty instanceObserves the value of the given client stored in the remote property.
remoteProperty:observeClientValue(somePlayer, function(newValue, oldValue)
print(newValue, oldValue)
end)
remoteProperty:setForClient(somePlayer, 1)
--> nil, nil
--> 1, nil
observe
RemoteProperty instanceObserves the value of the remote property.
local remoteProperty = RemoteProperty.new()
remoteProperty:observe(function(newValue, oldValue)
print(newValue, oldValue)
end)
remoteProperty:set(1)
--> nil, nil
--> 1, nil
observeClientsValue
RemoteProperty instanceObserves the values set for clients in the remote property.
local remoteProperty = RemoteProperty.new()
remoteProperty:observeClientsValue(function(client: Player, newValue, oldValue)
end)
destroy
RemoteProperty instanceRemoteProperty:
destroy
(
) →
(
)
Destroys the remote property and renders it unusable. All clients who have a specific value set for themselves in the remote property will be removed through RemoteProperty:removeForClient.