Zap Networking Solution

repository·0.6.x·Indexed 41 days ago

https://github.com/red-blox/zap

A high-performance, secure networking solution for Roblox that optimizes bandwidth and speed by packing data into specialized buffers. It includes a CLI for code generation and supports custom events, functions, and Luau/TypeScript type definitions. Current documentation covers version 0.6.x.

Tokens
16.3K
Snippets
56
Records
87
Agent score
51%

What's inside Zap

  1. Overview of Zap networking solution

    0.6.x

    Zap is a high-performance networking solution designed for Roblox. It focuses on minimizing bandwidth usage and maximizing speed by packing data into buffers with zero overhead.

    Key benefits include:

    • Bandwidth Efficiency: Data is packed into buffers, allowing the same information to be sent using significantly less bandwidth compared to standard methods.
    • High Performance: Packing and unpacking operations are designed to be faster than Roblox's generic encoding.
    • Extended Data Types: Supports a wider range of data types for network transmission.
    • Security: Uses buffers to make reverse engineering more difficult and performs validation on all received data to ensure security.
  2. Overview of Zap

    0.6.x
    Zap is a tool designed to generate highly efficient networking code for Roblox. It works by taking a description of your data and events (via an IDL) and generating specialized code tailored to your specific game requirements. This approach optimizes both bandwidth usage and CPU performance by using packed buffers and minimizing branching/calls during serialization.
  3. How Zap ensures networking security

    0.6.x

    Zap provides security through two layers:

    1. Buffer-based Encoding: Data is sent as byte arrays (buffers) rather than Roblox's standard self-describing encoding. Because the encoded data changes based on the specific data being sent, it is significantly harder for malicious actors to reverse engineer.
    2. Data Validation: Zap automatically validates all received data. If a client attempts to send invalid data, Zap catches it before it reaches your game logic, protecting your game from malicious clients sending malformed payloads.
  4. Use range syntax to constrain numbers and strings

    0.6.x

    Zap allows you to limit the valid range of numbers or the length of strings using a range syntax similar to Rust. Ranges are always inclusive of both the minimum and maximum values.

    Range Syntax Patterns:

    • min..max: Full range (e.g., 0..100)
    • min..: One-sided range (e.g., 0.. is 0 to ∞)
    • ..max: One-sided range (e.g., ..100 is -∞ to 100)
    • value: Exact value (e.g., 0 is exactly 0)
    • ..: No constraints (-∞ to ∞)

    Usage Examples:

    • Numbers: Constrain a u8 between 0 and 100: u8(0..100) or u8(..100).
    • Strings: Constrain a UTF-8 string length between 3 and 20 characters: string.utf8(3..20).
    • Arrays: Constrain array length between 10 and 20 items: u8[10..20].
    u8(..100)
    string.utf8(3..20)
    u8[10..20]
  5. Define Union (OR) types

    0.6.x

    Union types allow a value to be one of several types. Zap checks the type at runtime to determine how to serialize it.

    Rules:

    • You cannot use two types that are both runtime-checkable in a way that conflicts (e.g., you cannot have both u8 and u16 in the same union because they are both numbers).
    • You cannot use optional types (?) inside the union; instead, make the entire union optional.

    Example:

    type Union = (
    	string
    	| u32
    	| enum { "hello", "world" }
    	| enum "tag" { one { b: i8 }, two { c: buffer } }
    	| unknown
    	| Instance.Player
    	| Instance
    )

    Serialization Order: Zap checks types in the order they are defined in the union (e.g., checking if it's a specific enum string, then a table with a tag, then a string, then a number, etc.). If all checks fail, it serializes as unknown.

  6. Use CFrames and AlignedCFrames

    0.6.x

    Zap supports two types of CFrames:

    1. CFrame: A standard CFrame. Note that rotation matrices are compressed using axis-angle representation and are orthonormalized when sent. If you need a non-orthogonal CFrame, send the components separately.
    2. AlignedCFrame: Use this when you know the CFrame is axis-aligned (LookVector, UpVector, and RightVector align with world axes). This is significantly more bandwidth-efficient as rotation is represented by a single byte Enum.

    Warning: If the CFrame is not axis-aligned, AlignedCFrame will throw an error.

  7. How Zap optimizes bandwidth and CPU

    0.6.x

    Zap achieves high performance through two primary mechanisms:

    1. Bandwidth Optimization: Zap packs all data into buffers. These buffers use less space than standard Roblox serialization and benefit from additional compression when passed through RemoteEvents.
    2. CPU Optimization: Instead of using a generic serializer, Zap generates code specific to your data structures. This allows the generated code to use the most efficient packing/unpacking methods with minimal branching and minimal function calls.
  8. Use Roblox Instances and class-specific types

    0.6.x

    You can pass Roblox Instances through Zap. You can also specify a specific class using dot notation.

    Important Considerations:

    • Optionality: If a non-optional Instance results in nil (e.g., it hasn't replicated to the receiver yet), deserialization will fail and the packet will be dropped. Use optional types (Instance?) for instances that might not exist on the receiver.
    • Replication Timing: If deleting or parenting an instance to non-replicated storage, call SendEvents to flush the queue to ensure the deletion replicates before the instance is gone.

    Examples:

    • Generic instance: Instance
    • Specific class: Instance.BasePart (accepts BasePart and its subclasses like Part).
    type Part = Instance.BasePart
    
    type OptionalPlayer = Instance.Player?
  9. Define Unit and Tagged Enums

    0.6.x

    Unit Enums

    Used to represent a set of possible string values. They translate to Luau union types of strings. Example:

    type RoundStatus = enum { Starting, Playing, Intermission }

    Translates to: type RoundStatus = "Starting" | "Playing" | "Intermission".

    Tagged Enums

    Used to represent variants that each carry attached data. They require a tag field name. Example:

    type Tagged = enum "Type" {
    	Number { Value: f64 },
    	String { Value: string },
    	Boolean { Value: boolean },
    }

    Translates to: { type: "number", value: number } | { type: "string", value: string } | ....

    type RoundStatus = enum { Starting, Playing, Intermission }
    
    type Tagged = enum "Type" {
    	Number { Value: f64 },
    	String { Value: string },
    	Boolean { Value: boolean },
    }
  10. Integrate Zap with Lua tooling and plugins

    0.6.x

    Zap can output a Lua deserializer function that allows external plugins or scripts (like PacketProfiler) to read compressed remote data.

    To use this, you must pass the remote instance and all arguments sent through that remote to the generated deserializer function.

    Warning: Do not run side effects when deserializing this data yourself.

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local zap_deserialiser = require(path.to.deserialiser)
    
    local reliable = ReplicatedStorage:WaitForChild("ZAP_RELIABLE")
    local unreliable = ReplicatedStorage:WaitForChild("ZAP_UNRELIABLE")
    
    reliable.OnClientEvent:Connect(function(...)
    	local data = zap_deserialiser(reliable, ...)
    	print(data)
    end)
    
    unreliable.OnClientEvent:Connect(function(...)
    	local data = zap_deserialiser(unreliable, ...)
    	print(data)
    end)
  11. Define events in Zap

    0.6.x

    Events are the primary communication mechanism between the client and the server and form the basis of the generated Zap API. You define them in your configuration file using the event keyword.

    event MyEvent = {
    	from: Server,
    	type: Reliable,
    	call: ManyAsync,
    	data: (Foo: boolean, Bar: u32, Baz: string.utf8)
    }
  12. Generate code using the Zap CLI

    0.6.x

    To generate the Luau output files from your IDL configuration, run the zap command followed by the path to your .zap configuration file. This will generate the server and client output files specified in your configuration (or at default locations).

    zap path/to/config.zap