{"id":"protheeuz/satset","name":"satset","scope":"protheeuz","platform":"roblox","description":"High-performance, buffer-backed hybrid networking for Roblox with zero-allocation delta synchronization.","version":"0.5.0","latest":"0.5.0","versions":["0.3.1-rc.1","0.3.1","0.3.2","0.3.3","0.4.0-rc.1","0.4.0","0.4.1","0.4.2","0.5.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"682353810cae8a83338b52bdc1aab5ac96af25538bda696d08afb29b165b6037","likes":0,"downloads":0,"install":"forest install protheeuz/satset","url":"https://forest.dev/p/roblox/protheeuz/satset","files":"https://api.forest.dev/ai/package/roblox/protheeuz/satset/files","readme":"<div align=\"center\">\n\n# Sat·Set\n\n![CI](https://github.com/bookek/satset/actions/workflows/build.yml/badge.svg)\n![Version](https://img.shields.io/github/v/release/bookek/satset?label=version&color=orange)\n![Platform](https://img.shields.io/badge/platform-Roblox-00A2FF)\n![License](https://img.shields.io/github/license/bookek/satset?color=blue)\n\n</div>\n\n**sat·set** /sat-sèt/ *adjective (slang)* — Indonesian colloquialism for being rapid, efficient, and quick to act.\n\n> *\"Sat set, sampai.\"* — Indonesian for \"Swiftly done.\"\n\nSatset is a high-performance networking library for [Roblox](https://roblox.com). It handles the heavy lifting of buffer serialization and state synchronization. It connects low-level data packing with high-level state sync, offering a unified API for both stateless events (Packets) and delta-compressed channels.\n\nThe library is built on the principle that code on the hot path should not allocate. By using native Luau `buffer` operations and focusing on O(1) operations, Satset maintains performance even when syncing hundreds of entities per frame.\n\n# Performance Benchmarks\n\nSatset is designed for high-throughput scenarios. We maintain a [benchmark suite](benchmark/Benchmarks.md) that measures Satset against native RemoteEvents and other common implementations.\n\n## Dual-Mode Batching\n\nSatset provides two batching strategies. Users can tune the library for engine stability (segmenting large payloads) or raw throughput.\n\n| Test Case (1,000 items/frame) | Satset (Stability) | Satset (Latency) | Native Remotes |\n| :--- | :--- | :--- | :--- |\n| **Vectors** | 4.2 MB/s | **39.2 B/s** | 213.7 MB/s |\n| **Strings** | 18.4 MB/s | **118.9 B/s** | 140.2 MB/s |\n| **Booleans** | 485.4 KB/s | **38.1 B/s** | 160.9 MB/s |\n\n> [!NOTE]\n> **Payload Segmentation**: In standard use (Stability Mode), Satset segments payloads at 60KB to ensure frame-time consistency. Latency mode sends larger segments to allow better compression density when needed.\n\nDetailed methodology and raw data can be found in the [Benchmarks Report](benchmark/Benchmarks.md).\n\n# Documentation\n\nComprehensive technical documentation is available in the `docs/` directory:\n\n- **[Architecture & Getting Started](docs/guide/getting-started.md)**: High-level overview and initialization.\n- **[API Reference](docs/api/satset.md)**: Detailed breakdown of the `Satset` namespace.\n- **[Development Patterns](docs/guide/development-patterns.md)**: Design principles and performance constraints.\n- **[Security & Guard](docs/guide/security.md)**: Documentation on the token bucket rate limiting implementation.\n- **[Serialization Types](docs/api/types.md)**: Available data types for buffer-backed schemas.\n\n# Contributing\n\nContributions are welcome! Please review our **[Contribution Guide](CONTRIBUTING.md)** and **[Development Patterns](docs/guide/development-patterns.md)** before submitting a pull request.\n\n# Features\n\n## Hybrid Networking Engine\n\nSatset provides two distinct communication modes:\n\n- **Packets (Stateless)**: For one-off events like character actions or effects. These are batched automatically every frame to minimize RemoteEvent overhead.\n- **Channels (Stateful)**: The core state synchronization engine. It tracks changes to a defined schema and transmits only the dirty fields (deltas) using bitmask-based compression.\n\n## Implementation Details\n\n- **Zero-Allocation Pipeline**: Core operations happen in pre-allocated buffers. We use a callback-based dispatch model to minimize heap allocations on the hot path.\n- **Nested Structs**: Use `Satset.struct(schema)` to create reusable, composable type objects for complex nested schemas.\n- **Readable Type Names**: Provides human-readable aliases (`string`, `uint8`, `float64`, etc.) alongside shorthand forms for cleaner, more self-documenting schemas.\n- **Built-in Security**: Relies on Luau's native buffer bounds checks. Payload errors are caught via `pcall` to maintain stability without redundant manual checks.\n- **Buffer Safety**: Dynamic data (strings/arrays) is capped relative to the physical buffer size to prevent memory-related issues.\n- **Sanitized Floats**: Floating-point types (`f32`, `f64`, `Vector3`, etc.) are clamped to 0 if they are `NaN` or `±Infinity` to prevent state corruption.\n- **Header Stripping**: Automatically identifies fixed-size schemas and omits size headers when possible to reduce protocol overhead.\n- **MTU Management**: Automatic fragmentation for batches exceeding the [MTU](https://en.wikipedia.org/wiki/Maximum_transmission_unit) limit.\n- **Guard**: Built-in server-side rate limiting using a token bucket algorithm to prevent spam.\n\n# Architecture\n\nThe following diagram shows how data flows through Satset's internal modules, from the public API down to the wire.\n\n```mermaid\nflowchart TB\n    subgraph API[\"Public API\"]\n        DP[\"definePacket()\"]\n        DC[\"defineChannel()\"]\n        ST[\"struct()\"]\n    end\n\n    subgraph Serialization\n        SC[\"SchemaCompiler\"]\n        SR[\"Serializer\"]\n        SN[\"Sanitizer\"]\n        TP[\"Types\"]\n    end\n\n    subgraph Core\n        BT[\"Batcher\"]\n        GD[\"Guard\"]\n        BR[\"Bridge\"]\n    end\n\n    subgraph Networking\n        PK[\"Packet\"]\n        CH[\"Channel\"]\n    end\n\n    subgraph Transport[\"Wire\"]\n        RE[\"RemoteEvent\"]\n        URE[\"UnreliableRemoteEvent\"]\n    end\n\n    DP --> PK\n    DC --> CH\n\n    PK -->|\"encode(schema, data)\"| SR\n    ST -->|\"compile nested\"| SC\n    SR --> SC\n    SR --> SN\n    SC --> TP\n\n    PK -->|\"enqueue(id, payload)\"| BT\n    CH -->|\"encodeDelta(bitmask)\"| BT\n\n    BT -->|\"flush & segment\"| BR\n\n    BR --> RE\n    BR --> URE\n\n    RE -->|\"incoming payload\"| GD\n    URE -->|\"incoming payload\"| GD\n\n    GD -->|\"consume(player)\"| PK\n    GD -->|\"consume(player)\"| CH\n\n    SN -.->|\"clamp NaN/Inf\"| SR\n```\n\nFor a detailed step-by-step walkthrough of a packet's lifecycle, see the [Architecture Guide](docs/guide/architecture.md).\n\n# Usage\n\n## Installation\n\nAdd Satset to your `wally.toml`:\n\n```toml\nSatset = \"protheeuz/satset@0.3.2\"\n```\n\nThen run `wally install`.\n\n## Initialization\n\nSatset must be started once on both the **Server** and **Client** before defining any packets or channels.\n\n```luau\n-- In your main Server/Client entry point\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal Satset = require(ReplicatedStorage.Packages.Satset)\n \nSatset.start({\n    guard = {\n        maxTokens = 60,\n        refillRate = 30,\n    },\n    batching = {\n        reliableThreshold = 60000, -- Segmentation for stability\n    }\n})\n```\n\n## Packets (Stateless Events)\n\nPackets are for \"fire-and-forget\" events like combat hits, chat messages, or UI triggers.\n\n**Shared Definition:**\n\n```luau\n-- ReplicatedStorage/Networking/Packets.luau\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal Satset = require(ReplicatedStorage.Packages.Satset)\nlocal Types = Satset.Types\n \nreturn {\n    Damage = Satset.definePacket({\n        name = \"Damage\",\n        schema = {\n            targetId = Types.u32,\n            amount = Types.u16,\n            critical = Types.bool\n        },\n        reliable = true\n    })\n}\n```\n\n**Server Usage:**\n\n```luau\nlocal Packets = require(path.to.Shared.Packets)\n \n-- Sending to specific client\nPackets.Damage:fireClient(player, { targetId = 123, amount = 50, critical = true })\n \n-- Listening to client events\nPackets.Damage:listen(function(data, sender)\n    print(sender.Name .. \" dealt \" .. data.amount .. \" damage!\")\nend)\n```\n\n**Client Usage:**\n\n```luau\nlocal Packets = require(path.to.Shared.Packets)\n \n-- Sending to server\nPackets.Damage:fireServer({ targetId = 456, amount = 25, critical = false })\n \n-- Listening to server events\nPackets.Damage:listen(function(data)\n    print(\"Took \" .. data.amount .. \" damage!\")\nend)\n```\n\n## Channels (Stateful Synchronization)\n\nChannels are for data that has \"state\" (like health or positions). They use **delta-compression** and are much more efficient than packets for frequent updates.\n\n**Shared Definition:**\n\n```luau\n-- ReplicatedStorage/Networking/Channels.luau\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal Satset = require(ReplicatedStorage.Packages.Satset)\nlocal Types = Satset.Types\n \nreturn {\n    PlayerState = Satset.defineChannel({\n        name = \"PlayerState\",\n        schema = {\n            health = Types.u8,\n            position = Types.Vector3Quantized(2048)\n        },\n        unreliable = true,\n        resyncInterval = 5 -- Periodic keyframe to prevent drift\n    })\n}\n```\n\n**Server Usage:**\n\n```luau\nlocal Channels = require(path.to.Shared.Channels)\n \n-- Create an entity instance for a player\nlocal entity = Channels.PlayerState:create(player.UserId, {\n    health = 100,\n    position = Vector3.new(0, 5, 0)\n})\n \n-- Update state (only changed fields are transmitted)\nentity:set(\"health\", 85) \n```\n\n**Client Usage:**\n\n```luau\nlocal Channels = require(path.to.Shared.Channels)\n \n-- Subscribe to state changes\nChannels.PlayerState:subscribe(function(entityId, state)\n    print(\"Entity\", entityId, \"updated. Health:\", state.health)\nend)\n```\n\n# License\n\nSatset is distributed under the terms of the [MIT License](LICENSE).\n\nWhen Satset is integrated into external projects, we ask that you honor the license agreement and include Satset attribution into the user-facing product documentation.\n","readmeBorrowedFrom":{"version":"0.3.2","source":"wally"},"readmeTruncated":false}