Channel — Client API
When RunService:IsServer() is false at require-time, every Channel exposes the client method set below.
Method Table
| Method | Signature | Description |
|---|---|---|
send | (self, data: any) -> () | Sends data to the server. |
on | (self, callback: (data: any) -> ()) -> () | Registers a listener for packets sent from the server. Runs the middleware chain before invoking callback. |
Note the different on signature compared to the server: the client
callback only receives data, since there is no ambiguity about the
sender (it's always the server).
send
CombatNet.Position:send({ pos = character:GetPivot().Position })Sends the packet to the server.
on
CombatNet.Damage:on(function(data)
print("Took damage:", data.amount, "from", data.target)
end)Registers a client-side handler for packets sent by the server via sendTo, sendToAll, or sendToAllExcept.
A Channel only has one method set, decided once when the module is
required (based on RunService:IsServer()). Server-only methods
(sendTo, sendToAll, sendToAllExcept) simply don't exist on the
client's version of the channel, and vice versa for send — attempting
to call the wrong one errors immediately rather than doing nothing.
Reading a channel is what triggers the namespace's build. If your
client-side script reads CombatNet.Damage (to call :on(), for
example) long before the server does anything with CombatNet, and the
namespace relies on automatic build-on-first-access rather than an
explicit :build() call in the shared module, the client can end up
building the namespace before the server has published its packet IDs.
This is one of the most common real-world KravasNet bugs — see
Best Practices for how to avoid it.
Continue to Middleware & Reliability to learn how to validate and filter packet data.