Skip to content

Networking Hooks

Replecs allows you to intercept to the networking process in the client.

You can set a callback to be called after replication has been completed using replicator:after_replication(callback). This is useful for jecs signals because they will most likely be called in the middle of the networking process.

Hooking after replication will ensure that all the components are available to be used.

  • This is not a signal, so it doesn’t need to be disconnected.
  • Calling this when no replication is taking place will run the callback immediately.
  • This can also be called in the shared replicator that contains both the client and server replicators. Calling this in the server will always run the callback immediately.
local replicator = require("@shared/replicator")
world:added(components.car, function(entity)
replicator:after_replication(function()
-- safe to get the components since the car entity has been replicated entirely.
local car_model = world:get(entity, components.car_model)
local speed = world:get(entity, components.speed)
end)
end)

You can hook when a networked entity is created in the client by calling replicator:added(callback). The callback is run immediately right after creation, because of this, the entity will be empty when the callback runs. You can hook to after_replication to wait for the components. The entity you get is the client entity.

Unlike after_replication, this is a signal that needs to be disconnected, and this can only be called in the client replicator.

local replicator = require("@client/replicator")
local disconnect = replicator:added(function(entity)
replicator:after_replication(function()
local server_entity = replicator:get_server_entity(entity)
print("entity created from the server", server_entity)
end)
end)
disconnect() -- disconnect the signal

You can set hooks to each entity individually when an action is performed. To do this, you need to call replicator:hook(entity, action, ...). The arguments of this method will change depending on the action.

This method returns a disconnect function that you can call to remove the hook.

Setting the action to “changed” will make the callback run right after the component has been changed. This does not distinguish component additions and changes.

The arguments for the hook method will be:

  • entity: Entity - entity to hook
  • action: "changed" - “changed” action
  • replication_pair: Pair - what component to hook to. This pair should mimic how you track components in the server
  • callback: (entity: Entity, id: Id, component: Component) - callback to run when the component is changed
local replicator = require("@client/replicator")
replicator:hook(car, "changed", jecs.pair(replecs.reliable, components.speed), function(entity, id, speed)
print("car", entity, "changed speed to", speed)
end)
replicator:hook(enemy, "changed", jecs.pair(replecs.pair, components.attacking), function(entity, id)
print("enemy", entity, "is now attacking", jecs.pair_second(world, id))
end)

Setting the action to “removed” will make the callback run right before the component or pair gets removed. You can still access the component or pair right at this point.

The arguments for the hook method will be:

  • entity: Entity - entity to hook
  • action: "removed" - “removed” action
  • replication_pair: Pair - what component to hook to. This pair should mimic how you track components in the server
  • callback: (entity: Entity, id: Id) - callback to run when the component is removed
local replicator = require("@client/replicator")
replicator:hook(car, "removed", jecs.pair(replecs.reliable, components.speed), function(entity, id)
print("car", entity, "removed speed", world:get(entity, components.speed))
end)
replicator:hook(enemy, "removed", jecs.pair(replecs.pair, components.attacking), function(entity, id)
print("enemy", entity, "is no longer attacking", jecs.pair_second(world, id))
end)

Setting the action to “deleted” will make the callback run right before the entity gets deleted.

The arguments for the hook method will be:

  • entity: Entity - entity to hook
  • action: "deleted" - “deleted” action
  • callback: (entity: Entity) - callback to run when the entity is deleted
local replicator = require("@client/replicator")
replicator:hook(car, "deleted", function(entity)
print("car", entity, "was deleted")
end)

You can override actions. When this happens, replecs will not perform the action, but instead run the callback. This allows you add your own logic for changing/removing/deleting entities and components.

You override actions the same way you would hook to them, but calling replicator:override(entity, action, ...) instead, you cant override and hook at the same time for the same replication pair and action.

All action types behave the same way with the exception of “changed” since the component will not change at all.

local replicator = require("@client/replicator")
replicator:override(car, "changed", jecs.pair(replecs.reliable, components.speed), function(_, _, speed)
-- double the speed in the client (for some reason?)
world:set(car, components.speed, speed * 2)
end)
replicator:override(car, "removed", jecs.pair(replecs.reliable, components.speed), function()
-- set speed to 0 instead of removing it
world:set(car, components.speed, 0)
end)
replicator:override(enemy, "deleted", function(entity)
-- fade out the enemy and add lifetime to be deleted after 4 seconds
world:add(enemy, components.fade_out)
world:set(entity, components.lifetime, 4)
end)