Communicating between the client and the server is currently very difficult, especially when working with information that is crucial to gameplay such as replicating the aim directions of users, or sharing the current state of gameplay with all clients.
The current options (for client to server communication) are to either constantly send events to the server and responding to them individually, or to use systems like physics which are automatically replicated to the server anyway.
This topic proposes the addition of a system capable of syncing Attributes on objects from client to server. One of the ways this could be achieved would be to either create a separate Instance in charge of giving users “network ownership” over the attributes, or to allow any form of attribute to have an additional property that indicates if it can be manipulated client-side. Another approach would also be to manually grant attribute change permissions to players individually with a separate method.
From there, callbacks can also be introduced. If a callback is attached to an attribute, it can verify if the value (or the person it came from) is appropriate, and either update the value (editing / clamping it if necessary), or rejecting the edit by throwing an error or returning a special enum.
This takes a lot of effort away from developers by being able to sync information much easier to the server, without having to use RemoteEvents or create a system to network such information themselves, and any changes can be queued and sent alongside regular client information like physics.
An example of what this feature could look like:
-- server
--[[
Enum.AttributeSync.Fail for fail state, erroring to client and server
Enum.AttributeSync.Ignore to silently ignore this change
Enum.AttributeSync.Update to update the value on server
]]
-- called when the attribute is synced from client
player:SetSyncAttributeCallback(
"AimVector",
-- if multiple owners can be set, add an extra parameter for the player who sent the change
function(requested: Vector3)
local d = requested.Magnitude
-- check for suspicious values, NaN and large vectors
if d ~= d or d > 1.5 then
return Enum.AttributeSync.Fail, "invalid vector3 supplied"
end
-- output empty vector or unit vector
return Enum.AttributeSync.Update,
if d == 0 then Vector3.zero else requested.Unit
end
)
-- give partial ownership to the client to update this attribute
player:SetAttributeOwner("AimVector", player) -- maybe allow for multiple owners?
--client
-- update the aim vector locally
player:SetAttribute("AimVector", CURRENT_AIM)
-- request syncing of the attribute to server
player:SyncAttribute("AimVector") -- maybe add an Async version to check the response / error?
The other issues regarding the use of RemoteEvents to replicate data are:
The current method of constantly sending data to the server whenever possible creates many situations where you are using more remote event invokes than necessary. This leads to the server also receiving unnecessary amounts of OnClientEvent
s that will queue up and require the same portion of code to execute over and over. For users with a poor connection to the server, or in the case of the server lagging, this will greatly multiply the severity of the issue.
As well as sending / queuing more RemoteEvents, this also contributes to the total bandwidth of data sent by the client. In cases of extreme lag, this can result in abnormally large bandwidth when connection is re-established, as well as a lot of completely unnecessary data being transmitted to the server. It is also not possible to “Update” the content within a RemoteEvent. The data that is placed on invoke is the data that will be sent, so there is no way to just push the current value of the data as soon as possible, and to know when exactly to send this data.
RemoteEvents for data replication will usually come in one of three forms. Either the developer sends individual pieces of data into individual remote events, the developer creates a large structure to encompass all data that needs to be synced through a very few number of remote events, or the developer creates smaller chunks of structures to sync across only a couple of remote events. This is very inconsistent, and each application has major tradeoffs with efficiency, bandwidth, and complexity. Implementation of a system that is designed specifically for performing this task will improve all 3 aspects by introducing a fast, bandwidth efficient, and simple solution to the problem.
If possible, also, it would be useful to have an event for when the client has received information from the server (in order to sync attributes manually, or use remote events in a more efficient manner)