Replicators¶
Replicators are server-owned replicated state trees added in Vanguard 0.1.15.
They are designed for larger structured state where a single remote property
would become noisy or awkward.
Use a replicator when clients need to read and observe current state, while all mutation remains on the server.
Define a Replicator¶
local MatchService = Vanguard.CreateService({
Name = "MatchService",
Client = {
State = Vanguard.CreateReplicator({
Phase = "Lobby",
Score = {
Red = 0,
Blue = 0,
},
}),
},
})
During server startup, Vanguard replaces the marker with a server replicator
object and publishes a protocol 2 remote folder for clients.
Server API¶
Get¶
local fullState = self.Client.State:Get()
local score = self.Client.State:Get(nil, "Score.Red")
local playerState = self.Client.State:Get(player)
Get(player?, path?) returns a cloned value. When a Player has an override,
the override is used; otherwise the global state is used.
Set¶
Set replaces the global state and sends the full replacement to all clients.
SetPath¶
self.Client.State:SetPath("Score.Red", 3)
self.Client.State:SetPath({ "Players", player.UserId, "Ready" }, true)
Paths can be dot strings or arrays of string/number segments. Missing intermediate tables are created automatically. The replicated root must be a table when using path updates.
Patch¶
Patch recursively merges tables into the current root state. Non-table values
replace existing values.
Per-Player State¶
self.Client.State:SetFor(player, {
Phase = "Spectating",
})
self.Client.State:SetPathFor(player, "UI.Hidden", true)
self.Client.State:PatchFor(player, { Tutorial = { Step = 2 } })
self.Client.State:ClearFor(player)
Per-player overrides are removed automatically when the Player leaves.
ClearFor removes the override and sends the current global state to that
Player.
Observe¶
local connection = self.Client.State:Observe(function(player, change, state)
print(player, change.Operation, state.Phase)
end)
Server observers receive player, a change descriptor, and the effective state
after the change. player is nil for global updates.
Client API¶
Get¶
local MatchService = Vanguard.GetService("MatchService")
local state = MatchService.State:Get()
local redScore = MatchService.State:Get("Score.Red")
The first Get hydrates the client by invoking the server. Reads pass through
the same network guard pipeline as remote property reads.
Observe¶
local subscription = MatchService.State:Observe(function(state, change)
print(state.Phase)
end)
subscription:Disconnect()
Observe subscribes to future changes and asynchronously fetches the current
state. The initial callback receives change == nil.
ObservePath¶
local subscription = MatchService.State:ObservePath("Score.Red", function(value, change)
print("Red score", value)
end)
Path observers read the selected subtree after every replicated change. They do not filter changes by path yet; callbacks should be inexpensive.
Change Shape¶
type ReplicatorChange = {
Operation: "Set" | "SetPath" | "Patch" | "Clear",
Path: { string | number }?,
Value: any?,
}
Set carries the replacement state. SetPath carries the normalized path and
new value. Patch carries the patch table.
Network Security¶
Replicator reads use RemoteType = "Replicator" in the network context. They
can be rate-limited, authenticated, and verified with normal service network
rules:
Network = {
State = {
Authenticate = function(player)
return ProfileService:IsLoaded(player), "Profile is not ready"
end,
RateLimit = {
Limit = 10,
Window = 1,
},
},
}
Clients cannot mutate replicator state through Vanguard. Expose explicit server remote methods or signals for client requests, then validate, authenticate, verify, and mutate the replicator from server code.
Replicator vs RemoteProperty¶
| Use | Prefer |
|---|---|
| One small scalar or object | CreateProperty |
| Larger table state | CreateReplicator |
| Frequent partial updates | SetPath or Patch on a replicator |
| Per-player current value | Either, depending on shape |
| Event history | CreateSignal, not replicated state |
Replicators are state replacement tools, not event logs. If every historical change matters, use a signal or a server-owned queue and send explicit events.
Protocol Compatibility¶
Replicators require network protocol 2. Vanguard 0.1.14 clients use
protocol 1 and cannot safely interpret the new remote kind. Mixed protocol
installs fail during client service proxy construction with VG-NET-001.
Continue with Networking, Network Security, and Network Protocols.