Flare
Flare is Cluaupp’s network kernel: Zap-tight packing, batched reliable/unreliable remotes, and query RPC. You do not hand-wire remotes — write src/ReplicatedStorage/Shared/Net/Net.flare, run cluaupp build, and use the generated Net.clh / Net.luau API (Net.Hit.FireServer, Net.GetCoins.Invoke(), …). This header exposes the low-level Flare.write* / Flare.read* helpers and Flare.open used by generated code.
Header: #include <clpp/libs/flare.clh> (kernel). Gameplay includes the generated Net.clh. Runtime: CluauppLibs.Flare.
- Schema-first networking with typed packets and queries instead of ad-hoc Net tables.
- Binary buffers on the hot path (QuickNet-style cursors, instance sidecar arrays).
- Inbound client packets are gated by Ward — size cap, token bucket, and
from Clientdirection. Forged server-origin ids are struck, not dispatched. - Kernel only in games — gameplay calls generated
Net.*; custom codecs in advanced pipelines callFlare.write*/read*.
When not to use: trivial one-off remotes (Net), or declaring packets in CL++ without a .flare file (generation owns the game API). Keep’s own data handshake (NotifyReady) is separate — do not replace it with a Flare packet.
Example — packets and queries
Section titled “Example — packets and queries”src/ReplicatedStorage/Shared/Net/Net.flare (build generates Net.clh + Net.luau):
opt name = Net
packet Hit(Player target, i32 damage) from Clientpacket Announce(string text) from Serverpacket Spark(Vector3 pos) from Server unreliablequery GetCoins() -> i32| Kind | Generated API |
|---|---|
from Client | FireServer(...) on the client; Connect on the server (first arg is Player) |
from Server | Fire(recipient, …fields) / FireAll(…fields) on the server; Connect on the client (fields only — no recipient) |
query | Invoke(...) on the client; On on the server (first arg is Player, return the result) |
#pragma strict#include <clpp/roblox.clh>#include "Net.clh"
[[server]]void init() { Net.Hit~>Connect(func (Player player, Player target, int damage) { if (damage < 1 || damage > 25) { return; } post(player.Name); }); Net.GetCoins.On(func (Player player) { return 100; });}
[[client]]void attack(Player target) { Net.Hit.FireServer(target, 25);}
[[client]]void showCoins() { int coins = Net.GetCoins.Invoke();}Full join handshake: Connection.
Example — connection
Section titled “Example — connection”Client says it is ready; server replies with session identity. Place the schema next to gameplay remotes:
opt name = Net
packet Ready() from Clientpacket Welcome(i32 userId, f64 clock) from Serverquery Session() -> i32#pragma strict#include <clpp/roblox.clh>#include "Net.clh"#include <clpp/libs/keep.clh>#include <clpp/libs/ward.clh>
[[server]]void init() { Net.Ready~>Connect(func (Player player) { Ward.Grace(player, 2); Keep.Server.WaitFor(player); Net.Welcome.Fire(player, player.UserId, tick()); // recipient, then schema: i32, f64 }); Net.Session.On(func (Player player) { return player.UserId; });}
[[client]]void init() { Keep.Client.Init(); Net.Welcome~>Connect(func (int userId, double clock) { post(userId); }); Net.Ready.FireServer(); int me = Net.Session.Invoke();}After a legitimate server teleport, call Ward.Grace so movement checks do not look like a speed hack. Keep still owns persisted data; this channel is gameplay only.
Manual cursor (kernel):
#include <clpp/libs/flare.clh>
void pack() { FlareCursor c = Flare.cursor(); Flare.writeu16(c, 42); int n = Flare.readu16(c); // must use a fresh cursor on encoded buf in real code}Flare.cursor
Section titled “Flare.cursor”Returns: FlareCursor — empty write buffer (default capacity 64).
When: Building a payload byte-by-byte in generated or custom codecs.
Example
FlareCursor c = Flare.cursor();Flare.cursor (size)
Section titled “Flare.cursor (size)”Returns: FlareCursor — buffer with initial capacity size.
When: Known payload size to reduce reallocations.
Example
FlareCursor c = Flare.cursor(256);Flare.open
Section titled “Flare.open”Returns: FlareSession — registers packets/queries against remotes under host.
When: Generated Net.luau startup (not typical game CL++).
Example
FlareSession session = Flare.open(netModule);FlareSession::packet
Section titled “FlareSession::packet”Returns: auto — packet API object (generated spec: id, reliability, write/read fns).
When: Registering a fire-and-forget packet definition.
Example
session.packet(spec); // spec built by codegenFlareSession::query
Section titled “FlareSession::query”Returns: auto — query API object (Invoke client-side, On server-side).
When: Registering request/response RPC.
Example
session.query(spec);Flare.writeu8
Section titled “Flare.writeu8”Returns: Luau nil. Writes unsigned 8-bit integer at cursor offset (grows buffer as needed).
When: Packed enums or small counters.
Example
Flare.writeu8(c, 255);Flare.writeu16
Section titled “Flare.writeu16”Returns: Luau nil. Writes unsigned 16-bit integer (little-endian).
When: Length prefixes, ids.
Example
Flare.writeu16(c, 1000);Flare.writeu32
Section titled “Flare.writeu32”Returns: Luau nil. Writes unsigned 32-bit integer.
When: Timestamps, large ids.
Example
Flare.writeu32(c, 1);Flare.writei8
Section titled “Flare.writei8”Returns: Luau nil. Writes signed 8-bit integer.
When: Small signed deltas.
Example
Flare.writei8(c, -1);Flare.writei16
Section titled “Flare.writei16”Returns: Luau nil. Writes signed 16-bit integer.
When: Coordinates or scores in ±32k range.
Example
Flare.writei16(c, -500);Flare.writei32
Section titled “Flare.writei32”Returns: Luau nil. Writes signed 32-bit integer.
When: .flare i32 fields.
Example
Flare.writei32(c, 25); // damage in Hit packetFlare.writef32
Section titled “Flare.writef32”Returns: Luau nil. Writes IEEE float32.
When: Compact vectors and normals.
Example
Flare.writef32(c, 3.14);Flare.writef64
Section titled “Flare.writef64”Returns: Luau nil. Writes IEEE float64.
When: Full-precision numbers in custom payloads.
Example
Flare.writef64(c, 1.0);Flare.writebool
Section titled “Flare.writebool”Returns: Luau nil. Writes boolean as a single byte.
When: Flags in binary protocols.
Example
Flare.writebool(c, true);Flare.writestring
Section titled “Flare.writestring”Returns: Luau nil. Writes length-prefixed string (u16 length + bytes).
When: Names, chat, ids.
Example
Flare.writestring(c, "hi");Flare.writeVector3
Section titled “Flare.writeVector3”Returns: Luau nil. Writes three float32 components.
When: Positions and directions in packets.
Example
Flare.writeVector3(c, Vector3.new(0, 10, 0));Flare.writeVector2
Section titled “Flare.writeVector2”Returns: Luau nil. Writes two float32 components.
When: UI or 2D math on the wire.
Example
Flare.writeVector2(c, Vector2.new(1, 0));Flare.writeCFrame
Section titled “Flare.writeCFrame”Returns: Luau nil. Writes CFrame as 12 float32 components (runtime layout).
When: Replication of full transforms.
Example
Flare.writeCFrame(c, part.CFrame);Flare.writeColor3
Section titled “Flare.writeColor3”Returns: Luau nil. Writes Color3 in packed form used by Flare.
When: Tint or team color fields.
Example
Flare.writeColor3(c, Color3.new(1, 0, 0));Flare.writeUDim
Section titled “Flare.writeUDim”Returns: Luau nil. Writes scale + offset for UDim.
When: UI schema fields.
Example
Flare.writeUDim(c, UDim.new(0.5, 0));Flare.writeUDim2
Section titled “Flare.writeUDim2”Returns: Luau nil. Writes two UDim components.
When: UI size/position in .flare.
Example
Flare.writeUDim2(c, UDim2.new(1, 0, 1, 0));Flare.writeBrickColor
Section titled “Flare.writeBrickColor”Returns: Luau nil. Writes BrickColor id.
When: Legacy color fields.
Example
Flare.writeBrickColor(c, BrickColor.Red());Flare.writebuffer
Section titled “Flare.writebuffer”Returns: Luau nil. Writes nested buffer with length prefix.
When: Opaque blobs alongside structured fields.
Example
Flare.writebuffer(c, myBuf);Flare.writeInstance
Section titled “Flare.writeInstance”Returns: Luau nil. Appends instance to cursor sidecar and writes reference index.
When: Passing parts, tools, or characters (instances ride parallel to the buffer).
Example
Flare.writeInstance(c, part);Flare.readu8
Section titled “Flare.readu8”Returns: int — unsigned byte at cursor (advances offset).
When: Decoding generated packet bodies.
Example
int b = Flare.readu8(c); // 255 if that was writtenFlare.readu16
Section titled “Flare.readu16”Returns: int — unsigned 16-bit value.
When: Reading length or id fields.
Example
int n = Flare.readu16(c); // 1000Flare.readu32
Section titled “Flare.readu32”Returns: int — unsigned 32-bit value.
When: Large counters.
Example
int n = Flare.readu32(c);Flare.readi8
Section titled “Flare.readi8”Returns: int — signed 8-bit value.
When: Small signed fields.
Example
int n = Flare.readi8(c); // -1Flare.readi16
Section titled “Flare.readi16”Returns: int — signed 16-bit value.
When: .flare i16 fields.
Example
int n = Flare.readi16(c);Flare.readi32
Section titled “Flare.readi32”Returns: int — signed 32-bit value.
When: .flare i32 fields such as coin counts.
Example
int coins = Flare.readi32(c); // 100Flare.readf32
Section titled “Flare.readf32”Returns: double — float32 decoded to Luau number.
When: Vector components.
Example
double x = Flare.readf32(c);Flare.readf64
Section titled “Flare.readf64”Returns: double — float64 value.
When: High-precision custom data.
Example
double v = Flare.readf64(c); // 1.0Flare.readbool
Section titled “Flare.readbool”Returns: bool — boolean from one byte.
When: Flag decoding.
Example
bool ok = Flare.readbool(c); // trueFlare.readstring
Section titled “Flare.readstring”Returns: string — length-prefixed string.
When: Text fields in packets.
Example
string s = Flare.readstring(c); // "hi"Flare.readVector3
Section titled “Flare.readVector3”Returns: Vector3.
When: World-space replication.
Example
Vector3 p = Flare.readVector3(c);Flare.readVector2
Section titled “Flare.readVector2”Returns: Vector2.
When: 2D data.
Example
Vector2 v = Flare.readVector2(c);Flare.readCFrame
Section titled “Flare.readCFrame”Returns: CFrame.
When: Transform replication.
Example
CFrame cf = Flare.readCFrame(c);Flare.readColor3
Section titled “Flare.readColor3”Returns: Color3.
When: Color fields.
Example
Color3 col = Flare.readColor3(c);Flare.readUDim
Section titled “Flare.readUDim”Returns: UDim.
When: UI decoding.
Example
UDim d = Flare.readUDim(c);Flare.readUDim2
Section titled “Flare.readUDim2”Returns: UDim2.
When: UI size/position decode.
Example
UDim2 d2 = Flare.readUDim2(c);Flare.readBrickColor
Section titled “Flare.readBrickColor”Returns: BrickColor.
When: Legacy color decode.
Example
BrickColor bc = Flare.readBrickColor(c);Flare.readbuffer
Section titled “Flare.readbuffer”Returns: buffer — nested buffer slice.
When: Opaque attachment fields.
Example
buffer b = Flare.readbuffer(c);Flare.readInstance
Section titled “Flare.readInstance”Returns: Instance — next instance from the cursor sidecar (may be nil if absent).
When: Resolving written instance references.
Example
Instance inst = Flare.readInstance(c); // same part that was written