Generated API
A schema compiles to a server module, a client module and, with
TypesOutput, a shared types
module. This page lists everything they expose. Names are shown in the default Pascal
casing. Every module declares --!strict and passes it, so the types below are what a
strict script sees.
In the signatures below, ...Data stands for an event’s or function’s Data as parameters: one
parameter named Value for a single type, or one per element of a
type pack, named as the schema names them or Value1,
Value2… when it does not. ...Return is a function’s Return the same way. An event with no
Data takes a single nil parameter.
Requiring the modules
Section titled “Requiring the modules”local Net = require(ServerScriptService.Network.Server)local Net = require(ReplicatedStorage.Network.Client)| Module | Requirable from | When it loads |
|---|---|---|
| Server | the server only; errors elsewhere | Creates the two remotes if they are missing, publishes the schema signature, and checks both remotes’ classes. Under AutoStart = false, none of this happens until Start(). |
| Client | a client only; errors elsewhere | Waits for the two remotes, checks their classes, then checks the schema signature and errors on a mismatch. May yield – for ever, unless ClientConnectTimeout bounds the wait. |
| Types | anywhere | Nothing: it holds types and exported Read/Write pairs. |
Only the server module opens with --!native. Every Roblox server compiles native code, while a
client device that cannot logs Native code generation is not supported on this device for each
module that asks it to, so the client and types modules run interpreted, as most players’ clients
run code anyway. All three keep --!strict and --!optimize 2.
Requiring a second server or client module with the same RemoteScope
in the same Luau environment errors: An instance of BlinkBlox is already running with the remote scope "BLINK".
Module members
Section titled “Module members”| Member | Server | Client |
|---|---|---|
StepReplication() |
Sends every player’s queued reliable traffic. | Sends the client’s queued reliable traffic. |
SetRateLimitHandler(Handler?) |
Handler: (Player: Player, Event: string?, Refused: number) -> () |
Accepted and ignored: the client does not rate-limit. |
SetDecodeErrorHandler(Handler?) |
Handler: (Player: Player, Event: string?, Failure: string) -> () |
Handler: (Event: string?, Failure: string) -> () |
Limits |
With ExportLimits: a frozen table of the schema’s bounds. |
The same table. |
Rates |
With ExportRates: a frozen table of the rate limits the server enforces. |
The same table. |
SetPacketDropHandler(Handler?) |
Handler: (Player: Player, Reason: "Malformed" | "Oversized" | "Budget" | "Instances" | "Events", Refused: number, Detail: number) -> () |
Accepted and ignored: the client does not refuse packets. |
SetListenerErrorHandler(Handler?) |
Handler: (Player: Player, Event: string, Failure: string, Count: number) -> () |
Accepted and ignored: a client listener’s error surfaces in the output. |
Remotes |
{ Reliable: string, Unreliable: string }, the remotes’ names in ReplicatedStorage |
The same. |
Start() |
Only under AutoStart = false: creates and connects the remotes and the Heartbeat. A second call does nothing. |
– |
Connected |
– | Only under ClientConnectTimeout: true when the remotes were found in time, false when the module returned stubs. |
-
StepReplicationis connected toRunService.HeartbeatunlessManualReplicationis set, in which case you call it. -
The rate-limit handler is called at most once a second per player and event, with
Refusedthe number of refusals since the last call. It hears three kinds of refusal: an event or call over itsRate, a call over its function’sConcurrency(with the function’s name asEvent), and whole packets over the inbound byte budget, withEventnil– the last only while no packet-drop handler is installed. -
The packet-drop handler hears every packet the server refuses before decoding it, and every packet cut short at the event cap. It is called at most once a second per player and reason, with
Refusedthe packets refused since the last call, andDetail:ReasonRefused because DetailMalformedthe remote’s arguments were not a buffer and a table 0 Oversizedthe packet was over MaxPacketSizeits length in bytes Budgetthe player’s inbound byte budget could not pay for it its length in bytes Instancesit carried more than MaxInstancesPerPacketInstancesits instance count EventsMaxEventsPerPacketevents were decoded and the rest droppedthe events decoded With one installed, the server prints none of these warnings, and
Budgetno longer reaches the rate-limit handler. Without one, both behave as before 0.37.0. Nothing but a modified client sends a malformed, oversized or instance-stuffed packet; an honest one can overrun its budget after a network hitch. -
The decode-error handler receives the event the packet claimed to carry, or
nilif its index named none. On the server it is called at most once a second per player, channel and event, and without one the server is silent. On the client, without one, each failure is a warning. -
The listener-error handler hears every error a server listener throws: an event’s,
SyncorAsync,SingleorMany, reliable or unreliable, whether it arrived live, throughPredict, or from the queue replayed when.Onconnects; and a function’s, including a return value its serialiser refuses – that call is still answered with a failure. It is called at most once a second per player and event, withFailurethe error that call is about andCountthe errors since the last call, that one included. A player who has already left is reported at once withCount1. A polled event has no listener: the code iterating it is the game’s own. With one installed, the server prints none of those errors. Without one, they surface as they always have: aSynclistener’s raised on a thread of its own, anAsyncone’s on the thread it ran on, a function’s as the warning"Name" encountered an error, .... -
Every handler runs on a thread of its own, so one that yields or throws does not disturb decoding. Pass
nilto remove one.
Traffic counters
Section titled “Traffic counters”With option TrafficStats, and only with it, both
modules have two more members:
| Member | Server and client |
|---|---|
GetTrafficStats() |
Returns { Events: { [string]: Counts }, Reliable: Counts, Unreliable: Counts }, where Counts is { Sent: number, SentBytes: number, Received: number, ReceivedBytes: number }. |
ResetTrafficStats() |
Sets every count back to zero. |
- The totals run from the module’s start or the last
ResetTrafficStats(). Each call returns a fresh table, so keep one and subtract it from the next to get a rate. Eventshas one entry per event this module sends or receives, keyed by its path as the module exposes it –"Chat", or"Inner.Poll"inside a scope – present from the start with zeros. An event counts events inSent/Received, and its bytes in the buffer inSentBytes/ReceivedBytes: its one-byte index, the two-byte sequence number of anOrderedUnreliableevent, and its payload. The Instances that ride beside the buffer and what Roblox adds around a remote call are not counted. Functions are not listed; their calls and replies are counted inReliable.ReliableandUnreliablecount packets inSent/Receivedand whole buffers in the byte fields. A reliable packet is counted whenStepReplicationsends the batch, and holds everything batched that frame, functions included. An unreliable event is a packet of its own.- A reliable event is counted as sent when it is fired, as it joins the batch, so before the flush
its event counts can run ahead of
Reliable. - The server counts once per recipient, since each one is sent the bytes.
Firecounts one;FireListone per entry of the list, a player listed twice counting twice;FireExceptone per player but the one left out;FireAllone per player inPlayers:GetPlayers()when it is called, also for an unreliable event, which goes out throughFireAllClientsonce. A server with no players counts nothing. The server’sReliablecounts one packet per player flushed: a player’s own batch is one, and the broadcast batch is one for every player it is sent to, each counted with the batch’s bytes, though it goes out in a singleFireAllClientswhen it can. A client’s batch cut to the server’s packet limits counts each packet it is cut into. So a channel’sSentBytesis, after the flush, never less than theSentBytesof the events it carried. - A stream is counted when the scheduler sends it, as a
FireListto every player is: once per player, under the stream’s name inEventsand inUnreliable. Its bytes include the two-byte stamp and, for a state, the optional’s flag byte. A step that sends nothing counts nothing. - Received is counted once an event is decoded, before its rate limit and before a stale ordered event is discarded – those did arrive. A packet refused before decoding (malformed, oversized, over the inbound budget or its Instance limit) is not counted at all. A packet that fails part way counts as a packet with its whole length, and its events up to the failure.
- A fire that throws, or an unreliable one refused as too large, is not counted.
The counts are Luau numbers, exact up to 2^53. In edit mode both members exist and report zeros.
Events
Section titled “Events”Which members an event has depends on the side and on its From:
| Event | Server module | Client module |
|---|---|---|
From: Server |
Fire, FireAll, FireList, FireExcept |
On and Predict, or Iter when polled |
From: Client |
On and Predict, or Iter when polled |
Fire |
| Stream | Set, Clear, Urgent, SetFast, each taking the player first under Per: Player |
On, never polled, with the state and the server time |
Stamped From: Client |
On, never polled, with SentAt after the values |
Fire, taking the values only |
Predict exists only with option Predict. An event is
polled when it is declared Call: Polling or UsePolling
is set.
Sending
Section titled “Sending”| Member | Side | Signature | Sends to |
|---|---|---|---|
Fire |
server | (Player: Player, ...Data) -> () |
one player |
FireAll |
server | (...Data) -> () |
every player |
FireList |
server | (List: {Player}, ...Data) -> () |
each player in List |
FireExcept |
server | (Except: Player, ...Data) -> () |
every player but Except |
Fire |
client | (...Data) -> () |
the server |
- A reliable send is written into the recipient’s batch and sent on the next
StepReplication. - An unreliable send is sent at once, as its own packet. One larger than
MaxUnreliableSize, counting 6 bytes for each Instance it carries, is dropped with a warning. - A send throws if a value fails validation: always for a string, buffer or array length outside its
bounds or a map with more than 65535 entries, and for types, ranges and classes with
WriteValidations. Whatever the throw had already written is taken back out, so the rest of the batch is unaffected.
Receiving
Section titled “Receiving”| Member | Side | Signature |
|---|---|---|
On |
server | (Listener: (Player: Player, ...Data) -> ()) -> (() -> ()) |
On |
client | (Listener: (...Data) -> ()) -> (() -> ()) |
Predict |
server | (Player: Player, ...Data) -> () |
Predict |
client | (...Data) -> () |
Iter |
server | () -> iterator of (Index: number, Player: Player, ...Data) |
Iter |
client | () -> iterator of (Index: number, ...Data) |
Next |
both | Deprecated alias of Iter, the same function. |
-
Onreturns a function that disconnects the listener. -
A
Singleevent keeps one listener. A secondOnreplaces the first and warns, and the first listener’s disconnect function stops doing anything. AManyevent keeps them all. -
A
Synclistener is called on the decode thread and must not yield; anAsyncone runs on a thread of its own. SeeCall. -
A reliable event that arrives with no listener is queued and replayed to the first listener that connects. The server keeps at most 256 per event and drops the rest silently; the client warns past 256. An unreliable event with no listener is dropped.
-
Predictdelivers to this side’s own listeners, exactly as an arriving event would be delivered, queue included. It sends nothing. -
Itertakes rows out of the event’s queue as it goes, so each row is seen once:for Index, Player, Value in Net.Jump.Iter() do-- ...endOn the server a polled queue holds at most 256 x
Players.MaxPlayersrows; the rest are dropped.
Functions
Section titled “Functions”| Function | Server module | Client module |
|---|---|---|
From: Client (the default) |
On |
Invoke |
From: Server |
Invoke |
On |
| Member | Side | Signature |
|---|---|---|
Invoke |
client | (...Data) -> (...Return), or a Future or Promise |
Invoke |
server | (Player: Player, ...Data) -> (...Return), or a Future or Promise |
On |
server | (Listener: (Player: Player, ...Data) -> (...Return)) -> () |
On |
client | (Listener: (...Data) -> (...Return)) -> () |
What Invoke returns depends on the function’s Yield:
Yield |
Invoke returns |
On failure |
|---|---|---|
Coroutine |
the return values, after yielding | throws There was an exception while processing "Name". |
Future |
Future.Try(...): a future of (Success, ...Return) |
the future’s success is false |
Promise |
Promise.new(...) resolving with the return values |
the promise rejects; cancelling it releases the call |
- A call fails when the listener errors, when its return value fails to serialise, when a rate limit
refuses it, when the player already has the function’s
Concurrencycalls running, when the server’s queue for a function with no listener is full, when the call is not answered withinInvocationTimeout(10 seconds), and, on the server, when the player leaves or has already left. - At most 32 calls may be outstanding at once: per client, and per player on the server. The 33rd
Invokeerrors at once. Onkeeps one listener and returns nothing; a secondOnreplaces the first. Calls that arrive before it connects are queued and run when it does – on the server up to 256, past which each is answered with a failure.- The listener’s return values are the reply. An error in the listener is warned on the listening side and fails the caller.
Exported types
Section titled “Exported types”A type declared with export gets a Read/Write pair in all three modules, under its name:
| Member | Signature |
|---|---|
Name.Read |
(Buffer: buffer) -> Name |
Name.Write |
(Value: Name) -> buffer |
They serialise one value into a buffer of exactly its size and back, with the same encoding and the
same receive-side checks the events use. They work in edit mode too. A type containing an Instance
or unknown cannot be exported (E3013). See Exports.
Types and scopes
Section titled “Types and scopes”Every named type in the schema is declared in each module as a Luau export type, so
Net.Name works in a type annotation. A scope becomes a nested table:
Net.Combat.Hit.Fire(...). A type inside a scope is exported as Scope_Name, for example
Net.Combat_Damage.
Casing
Section titled “Casing”option Casing renames the generated members. The names of
your own declarations are never changed.
Pascal (default) |
Camel |
Snake |
|---|---|---|
Fire |
fire |
fire |
FireAll |
fireAll |
fire_all |
FireList |
fireList |
fire_list |
FireExcept |
fireExcept |
fire_except |
On |
on |
on |
Iter |
iter |
iter |
Next |
next |
next |
Predict |
predict |
predict |
Invoke |
invoke |
invoke |
Read |
read |
read |
Write |
write |
write |
Set |
set |
set |
Clear |
clear |
clear |
Urgent |
urgent |
urgent |
SetFast |
setFast |
set_fast |
StepReplication |
stepReplication |
step_replication |
SetRateLimitHandler |
setRateLimitHandler |
set_rate_limit_handler |
SetDecodeErrorHandler |
setDecodeErrorHandler |
set_decode_error_handler |
SetPacketDropHandler |
setPacketDropHandler |
set_packet_drop_handler |
SetListenerErrorHandler |
setListenerErrorHandler |
set_listener_error_handler |
Remotes |
remotes |
remotes |
Start |
start |
start |
Connected |
connected |
connected |
GetTrafficStats |
getTrafficStats |
get_traffic_stats |
ResetTrafficStats |
resetTrafficStats |
reset_traffic_stats |
The fields of GetTrafficStats‘s result follow the casing too: Events, Reliable, Unreliable,
Sent, SentBytes, Received and ReceivedBytes under Pascal; events, sentBytes,
receivedBytes and the rest under Camel; sent_bytes and received_bytes under Snake. The keys
of Events are your events’ names, unchanged.
Edit mode
Section titled “Edit mode”When RunService:IsRunning() is false – in edit mode, and in Roblox stories (Hoarcekat, UI Labs,
Flipbook) – no remotes exist, and both modules return stubs that keep the real API’s shape:
| Member | Stub |
|---|---|
Fire, FireAll, FireList, FireExcept |
does nothing |
On (events and functions) |
does nothing and returns a disconnect function that does nothing |
Iter, Next |
returns an iterator that ends at once, so a for loop runs zero times |
Predict |
does nothing |
A stream’s Set, Clear, Urgent, SetFast |
do nothing |
Invoke |
does nothing and returns nil |
StepReplication, SetRateLimitHandler, SetDecodeErrorHandler, SetPacketDropHandler, SetListenerErrorHandler |
do nothing |
Remotes |
the real names |
Start |
does nothing |
Connected |
false |
GetTrafficStats, ResetTrafficStats |
the real functions; nothing is sent in edit mode, so every count is zero |
exported Read, Write |
work normally |
A client under ClientConnectTimeout that did
not find its remotes in time returns the same stubs, with one difference: Invoke fails at once with
The client is not connected to a server, as a real call fails on its timeout, instead of returning
nil.
The stub is returned before the module checks which side it is on, so a story can require either
module – but not both. The RemoteScope guard above runs first, in edit mode too, and the server
and client modules of one schema share a scope, so the second one required errors.
Reserved names
Section titled “Reserved names”| Name | Why |
|---|---|
StepReplication, SetRateLimitHandler, SetDecodeErrorHandler, SetPacketDropHandler, SetListenerErrorHandler, GetTrafficStats, ResetTrafficStats, Limits under ExportLimits, and Rates under ExportRates |
Module members; GetTrafficStats and ResetTrafficStats are reserved without TrafficStats too, so turning it on never starts refusing a schema. A top-level event, function, scope or type may not take these names, nor, under Camel or Snake casing, the spelling the module gives them there (stepReplication, step_replication, …) (E3005). |
Remotes; Start under AutoStart = false; Connected under ClientConnectTimeout |
Module members added after 0.37.0, refused in the spelling the casing gives them for a top-level event, function, scope or exported type (E3005). A plain type may keep the name: it is a Luau type, not a key of the module. |
BLINK_ENTRY, BLINK_QUEUE, BLINK_BUFFER_SAVE, BLINK_INVOCATIONS, BLINK_DROP_REASON, BLINK_TRAFFIC_COUNTS, BLINK_TRAFFIC_STATS, BLINK_EVENTS_SYMBOL, BLINK_STREAM |
Types the module declares for itself. A top-level type of that name would redefine one (E3005). |
Built-in Luau types: any, never, number, thread |
A declared type is exported under its own name, and Luau refuses export type number = number (E3005, since 0.32.0). |
Roblox types the module uses: Player, RemoteEvent, UnreliableRemoteEvent, Vector3, and any class the schema names in Instance(...) |
A top-level type of that name would refer to itself and shadow every use of the Roblox type in the module (E3005, since 0.32.0). A type inside a scope is exported with the scope’s name in front, so it may take these names. |
BlinkBlox’s own types: boolean, buffer, string, unknown, Instance, CFrame, Color3, DateTime, BrickColor and the rest |
The parser reads them as primitives, so a declaration cannot be named after one (E2002). |
Luau keywords (end, local, …) |
A named type-pack element becomes a parameter, so it must be a Luau identifier (E3005). Struct fields, flags and tags may be keywords; they are quoted. |
Player, Buffer, Load, Size, Success and other names the generated functions use |
Refused as type-pack element names, which would shadow them (E3005); the diagnostic names the clash. |
| A tagged enum’s tag | May not also be a field of one of its variants (E3005). |
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Outstanding invocations | 32 per client; 32 per player on the server |
| Invocation timeout | InvocationTimeout, 10 seconds by default |
| Queued reliable events with no listener | 256 per event (server drops, client warns) |
| Queued calls with no listener | 256 per function on the server, then answered with a failure |
| Calls running at once | Concurrency per player per function on the server, when declared; the rest are answered with a failure |
| Polled queue on the server | 256 x Players.MaxPlayers rows per event |
| Enum values or tagged-enum variants | 256 |
| Declarations per channel | 256 (reliable events and functions share one channel, unreliable events the other) |
| Unbounded string, buffer or array | 65535 bytes or elements |
