Authority
A server-authoritative state object whose fields replicate to clients through attributes on an instance. You create it on both sides from the same module with the same default table; the server owns the values and the clients receive them.
How it works:
-
Each key of
propertiesbecomes a field. Its initial value is the matching attribute onparentif one exists, otherwise the default you passed in. -
Server: writing
authority.Key = valuestores the value and callsparent:SetAttribute("Key", value), which Roblox replicates. All defaults are written to the attributes as soon as the object is created. Only string keys can be attributes; other keys are kept locally with a warning. -
Client: writing any field errors. Reading returns the latest value, which is kept in sync
by listening to
parent.AttributeChanged, so clients see server writes without any remotes. - Both sides also pick up attribute changes made outside the object (for example from the Studio properties panel) for keys that are currently tracked.
-- ReplicatedStorage/MatchState.luau (required by both server and client)
local Authority = require(path.to.Authority)
return Authority(workspace, {
Phase = "Lobby",
TimeLeft = 60,
})
-- Server
local MatchState = require(ReplicatedStorage.MatchState)
MatchState.Phase = "Playing" -- sets workspace attribute "Phase", replicates
MatchState.TimeLeft -= 1
-- Client
local MatchState = require(ReplicatedStorage.MatchState)
print(MatchState.Phase) -- "Playing" once replicated
workspace:GetAttributeChangedSignal("TimeLeft"):Connect(function()
print(MatchState.TimeLeft)
end)
Setting a field to nil on the server removes the attribute and the object stops tracking that
key, so prefer sentinel values over nil for optional state. Do not use Destroy as a key; it is
reserved for the cleanup method.
Credits: written by KashTheKing. No third-party dependencies.
Installation and guide: Authority package page.
Types
AuthorityObject
interface AuthorityObject {Destroy: (self: Authority<A>) → ()--
Disconnects the attribute listener and disables the object. See Authority:Destroy.
}
The object returned by Authority.new: all the fields of your properties table A
(read on both sides, written on the server only) plus Destroy. It is a userdata proxy, not a
table, so you cannot iterate it or use rawget/rawset on it.
Functions
new
Authority.new(parent: Instance,--
The instance whose attributes carry the state. It must replicate to the clients that need the values (e.g. under workspace or ReplicatedStorage).
properties: A--
Dictionary of default values. Keys must be strings to replicate; values must be attribute-compatible types.
) → Authority<A>--
A proxy exposing properties' fields plus Destroy.
Creates an Authority whose fields mirror attributes on parent. Call it on both the server
and the client with the same defaults. The module itself is this function, so use
Authority(parent, properties).
On the server every default is immediately written to parent as an attribute (existing
attributes win over defaults), and subsequent writes to the object replicate the same way. On
the client the object is read-only and follows the server's attribute values.
Errors
| Type | Description |
|---|---|
| "Parent must a valid instance" | `parent` is not an Instance. |
| "Properties must be a valid dictionary" | `properties` is not a table. |
| "Client attempted to change server key" | Raised later, when a client assigns to any field of the returned object. |
Destroy
Authority:Destroy() → ()
Stops listening to parent.AttributeChanged and removes every metamethod from the proxy, so
any later field access errors. The attributes already written to parent are left in place.
Call it when the state is no longer needed, for example when parent is about to be destroyed.