Replicating Entities
Replicating Entities
Section titled “Replicating Entities”Replecs replication is per-entity. This means that you need to mark each entity to be networked.
You can do this by calling set_networked on the server replicator. This will allocate an entity creation event to be sent to the client.
local world = require("world")local replicator = require("@server/replicator")
local npc = world:entity()replicator:set_networked(npc)Replicating Components
Section titled “Replicating Components”After marking an entity as networked, you need to mark each component that you want to replicate and how you want to replicate it.
This allows for a highly granular control over replication for each entity.
Replication Types
Section titled “Replication Types”Components/Tags
Section titled “Components/Tags”Components and tags are replicated with set_reliable. You pass the component you want to replicate.
local world = require("world")local replicator = require("@server/replicator")local components = require("@shared/components")
local npc = world:entity()replicator:set_networked(npc)
world:set(npc, components.health, 100)world:add(npc, components.alive)-- mark components to be replicatedreplicator:set_reliable(npc, components.health)replicator:set_reliable(npc, components.alive)Unreliable Components
Section titled “Unreliable Components”Components can be marked to be replicated unreliably with set_unreliable.
This will send the latest value of the component to the client no matter whether it changed or not. This kind of replication should be used when the component value changes too quickly in the server (every frame).
Replecs will also automatically split unreliable packets to stay under a 900 byte budget, so they fit in the 1KB unreliable limit.
A single entity larger than the budget by itself is still sent alone, over the budget, so keep unreliable values small.
local world = require("world")local replicator = require("@server/replicator")local components = require("@shared/components")
local npc = world:entity()replicator:set_networked(npc)
world:set(npc, components.position, Vector3.new(0, 0, 0))replicator:set_unreliable(npc, components.position)Relationships
Section titled “Relationships”Pairs are replicated with set_relation. You pass the relation you want to replicate, and every pair of that relation on the entity will be replicated.
Note that if the relation target is an entity, this entity also needs to be marked as networked.
local world = require("world")local replicator = require("@server/replicator")local components = require("@shared/components")
-- create a relationlocal npc = world:entity()local player = world:entity()
replicator:set_networked(npc)replicator:set_networked(player)
-- create a pairworld:add(npc, jecs.pair(components.attacking, player))replicator:set_relation(npc, components.attacking)Specific Pairs
Section titled “Specific Pairs”If you only want to replicate a single pair instead of every target of a relation, use set_pair with the full pair id.
Only that pair is tracked, other targets of the same relation are not replicated.
local world = require("world")local replicator = require("@server/replicator")local components = require("@shared/components")
local npc = world:entity()local player = world:entity()local enemy = world:entity()
replicator:set_networked(npc)replicator:set_networked(player)replicator:set_networked(enemy)
world:add(npc, jecs.pair(components.attacking, player))world:add(npc, jecs.pair(components.attacking, enemy))
-- only (attacking, player) is replicatedreplicator:set_pair(npc, jecs.pair(components.attacking, player))Pairs with values that change every frame can be replicated unreliably with set_unreliable_pair.
It behaves like set_unreliable, the pair must have a value.
world:set(npc, jecs.pair(components.distance_to, player), 12)replicator:set_unreliable_pair(npc, jecs.pair(components.distance_to, player))Relationship Values
Section titled “Relationship Values”Pairs that contain values can be marked like normal pairs, but replecs will only replicate pair values if the relation or the target of the pair is a component.
local world = require("world")local replicator = require("@server/replicator")
local value_relation = world:component()local no_value_relation = world:entity()
local npc = world:entity()local target = world:entity()
replicator:set_networked(npc)replicator:set_networked(target)
world:set(npc, jecs.pair(value_relation, target), 10)world:add(npc, jecs.pair(no_value_relation, target))
-- this will replicate pair valuesreplicator:set_relation(npc, value_relation)-- this will not replicate pair valuesreplicator:set_relation(npc, no_value_relation)Once Components
Section titled “Once Components”Components can be marked to replicate only their addition and removal with set_once.
Value changes are ignored, which is useful for components that are set once and never change, like a name or a model id.
If the value does change and you need to send it, call force_change. The current value is sent on the next update.
local world = require("world")local replicator = require("@server/replicator")local components = require("@shared/components")
local npc = world:entity()replicator:set_networked(npc)
world:set(npc, components.name, "Guard")replicator:set_once(npc, components.name)
-- later, this change is not replicated by itselfworld:set(npc, components.name, "Captain")-- send it explicitlyreplicator:force_change(npc, components.name)Stopping Replication
Section titled “Stopping Replication”Entities and components can be stopped from being replicated at any time.
Entities
Section titled “Entities”You can stop an entity from being replicated with stop_networked.
This will also allocate an event to delete the entity in the client.
replicator:stop_networked(npc)All your components will still remain in the entity. You can reactivate the entity by calling set_networked again.
This will correctly replicate back your entity with all its components. This is useful for streaming entities in and out dynamically.
Components
Section titled “Components”You can stop a component from being replicated with the matching stop_* function.
This will also allocate an event to remove the component entirely in the client
replicator:stop_reliable(npc, components.health)replicator:stop_reliable(npc, components.alive)replicator:stop_unreliable(npc, components.position)replicator:stop_once(npc, components.name)replicator:stop_relation(npc, components.attacking)replicator:stop_pair(npc, jecs.pair(components.attacking, player))replicator:stop_unreliable_pair(npc, jecs.pair(components.distance_to, player))A component stopped this way does not come back if the entity is stopped and revived with set_networked,
you need to mark it again.