Data Types
Every field inside a channel's schema table must be built with a KravasNet type constructor.
Primitives are values, not factories. ByteNet 0.4.6 pre-instantiates
every primitive type once, at module load (bool(), uint8(), etc. are
called internally, exactly once, inside ByteNet's own init.luau). This
means KravasNet.bool, KravasNet.int8, KravasNet.vec3, and the rest
of the primitives listed below are already-built type descriptors —
do not call them (KravasNet.int8() will error with "attempt to call
a table value"). The composite helpers (optional, array, struct,
map) are genuine functions and must be called with their type
argument(s).
CombatNet:add("Damage", {
amount = KravasNet.float32, -- no parens
target = KravasNet.inst, -- no parens
})Primitive Types
| KravasNet field | Lua/Roblox equivalent | Notes |
|---|---|---|
KravasNet.bool | boolean | 1 byte. |
KravasNet.uint8 | number | Unsigned 8-bit integer (0–255). |
KravasNet.uint16 | number | Unsigned 16-bit integer. |
KravasNet.uint32 | number | Unsigned 32-bit integer. |
KravasNet.int8 | number | Signed 8-bit integer. |
KravasNet.int16 | number | Signed 16-bit integer. |
KravasNet.int32 | number | Signed 32-bit integer. |
KravasNet.float32 | number | Single-precision float. |
KravasNet.float64 | number | Double-precision float. |
KravasNet.string | string | Length-prefixed UTF-8 string. |
KravasNet.vec2 | Vector2 | Packed as two floats. |
KravasNet.vec3 | Vector3 | Packed as three floats. |
KravasNet.cframe | CFrame | Position + rotation. |
KravasNet.buff | buffer | Raw byte buffer, copied directly. |
KravasNet.inst | Instance | Sent as a reference (see below), resolved back to the same Instance on the receiving side. |
KravasNet.unknown | any | Escape hatch for untyped/dynamic data — also sent by reference; use sparingly. |
KravasNet.nothing | nil | Represents an empty payload. |
inst and unknown don't serialize their value into the buffer at all —
ByteNet stores the actual Luau value in a small per-packet reference
table sent alongside the buffer, and writes only a 1-byte index into
the buffer itself. This is fast, but each packet instance can only carry
up to 255 such references (1 byte per reference slot).
Composite Types
| KravasNet function | Description |
|---|---|
KravasNet.array(type) | An array/list of a given type. |
KravasNet.optional(type) | Marks a field as optional (may be nil). |
KravasNet.struct(schema) | A nested table of named fields — used internally to wrap every channel's schema. |
KravasNet.map(keyType, valueType) | A dictionary-like table with typed keys and values. |
These are plain functions — call them with their type argument(s), which themselves should be primitives (unparenthesized) or other composites.
Example: composite schema
InventoryNet:add("Update", {
items = KravasNet.array(KravasNet.struct({
id = KravasNet.uint32,
quantity = KravasNet.uint16,
})),
note = KravasNet.optional(KravasNet.string),
})Choosing the right type
| Scenario | Recommended type |
|---|---|
| Health, ammo count, small counters | uint8 / uint16 depending on max value |
| Damage amounts, positions | float32 |
| High-precision timestamps or physics data | float64 |
| Player/character references | inst |
| Free-form debug payloads | unknown — but avoid in hot paths, and remember the 255-reference-per-packet ceiling |
| A field that may or may not be present | optional(type) |
| Lists of structured items | array(struct({ ... })) |