{"id":"qscythee/sequenaplus","name":"sequenaplus","scope":"qscythee","platform":"roblox","description":"Mirrored from the Wally registry.","version":"0.2.0","latest":"0.2.0","versions":["0.2.0"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"873fe334828317937e01e60156ce6614fc08cb990d63187f3b9740da635a6d13","likes":0,"downloads":0,"install":"forest install qscythee/sequenaplus","url":"https://forest.dev/p/roblox/qscythee/sequenaplus","files":"https://api.forest.dev/ai/package/roblox/qscythee/sequenaplus/files","readme":"# Sequena+\n\nSequena+ is the client-facing name for this redesigned networking library.\nThe installed Wally package and Luau module are `qscythee/sequenaplus` and\n`Sequena` respectively.\nGenerated by [Rojo](https://github.com/rojo-rbx/rojo) 7.7.0.\n\n## Getting Started\nTo build the place from scratch, use:\n\n```bash\nrojo build -o \"SequenaPlus.rbxlx\"\n```\n\nNext, open `SequenaPlus.rbxlx` in Roblox Studio and start the Rojo server:\n\n```bash\nrojo serve\n```\n\nWally & pesde Support,\n```bash\nwally add qscythee/sequenaplus@0.2.0\n```\n(same for pesde)\n\n\nFor more help, check out [the Rojo documentation](https://rojo.space/docs).\n\n## Usage Example\n```lua\nlocal Data = Sequena.Data\n\nlocal MyEvent = Sequena.Define(\n    {\n        Name = \"Action\",\n        Reliable = true,\n        UseDelta = true,\n    },\n    Data.U8,\n    Data.Vector3,\n    Data.String\n)\n```\n\nPackets must have non-empty names. Names use deterministic IDs, so adding or\nreordering definitions does not change the wire ID. Names must be unique and\nstable between the server and client; packet names are part of the network\nprotocol.\n\nFor more help, join this Discord Server [Link](https://discord.gg/D5xKeWHsgN)\n\n## Documentation site\n\nThe VitePress documentation site lives in `docs/`. To develop or preview it:\n\n```bash\ncd docs\nnpm install\nnpm run dev\n```\n\nBuild it with `npm run build`. The `main` branch deploys the generated site to\nGitHub Pages through `.github/workflows/docs.yml`.\n\n## Functional library tests\n\nThe repository includes a client/server functional test harness in\n`tests/functional/` and\n`integration.project.json`. Sync it with Rojo:\n\n```bash\nrojo serve integration.project.json\n```\n\nOpen a place in Studio, connect the Rojo plugin, and press Play. The server\nand client runners report assertions through the Roblox TestService output.\nThe harness covers primitive values, Roblox values, tables, structs,\ncomposites, dynamic values, delta packets, runtime validation, and\nrequest/response packets. Performance benchmarking lives separately under\n`benchmarks/networking/`.\n\n## Networking benchmark\n\n`benchmarks/networking/` is an isolated benchmark project. It has its\nown Rojo project and Wally manifest, and reports engine-observed send/receive\nKbps median and peak, message tension, RTT, loss, and sampled CPU time. See\nits README for setup and the transport list.\n\n## Configuration\n\nConfiguration can be overridden after requiring the Sequena module and before defining\npackets. Unknown sections/options are rejected.\n\n```lua\nSequena.Configure({\n    Security = {\n        MaxStringSize = 4096,\n        MaxArraySize = 500,\n    },\n    Network = {\n        MaxBatchSize = 32768,\n    },\n})\n```\n\nConfiguration is locked after the first packet is defined so all packet\nserializers use the same limits.\n\nIncoming payloads are bounds-checked before reads, compressed/decompressed\npayload sizes are limited, oversized strings/buffers/tables are rejected,\nunknown packet/type IDs are rejected, and server inbound traffic is rate\nlimited per player.\n\n## Data Types\n\nUse `Sequena.Data` for primitive schema values instead of writing type-name\nstrings directly:\n\n```lua\nlocal Data = Sequena.Data\n\nlocal Packet = Sequena.Define({\n    Name = \"Inventory/Updated\",\n}, Data.U8, Data.Vector3F16, Data.String)\n```\n\nComposite types such as `Data.Array`, `Data.Optional`, `Data.Literal`,\n`Data.Or`, `Data.And`, `Data.Map`, `Data.Struct`, `Data.Enum`, and `Data.Bitfield` are\nalso available.\n\nThe public table is assembled internally from focused datatype modules under\n`src/Datatypes`: `Numbers`, `Primitives`, `Roblox`, `RobloxSerializers`,\n`Dynamic`, `DynamicSerializers`, `Checks`, `Resolver`, and `Composites`.\nDatatype modules register their serializers/deserializers against the active buffer context; composite builders use the same context for\nschema resolution and bounds enforcement.\n\n### Typed packet APIs\n\nSequena+'s public schema fields carry their Luau value type. The config-first\nvararg form provides precise positional inference for every packet field:\n\n```lua\nlocal Data = Sequena.Data\n\nlocal Request = Sequena.Define({\n    Name = \"Inventory/Get\",\n}, Data.U32, Data.String)\n\nRequest.OnServerEvent:Connect(function(Player, UserId, ItemName)\n    -- Player: Player, UserId: number, ItemName: string\nend)\n\nRequest:Fire(42, \"Potion\")\n```\n\nPacket direction is enforced at runtime. Clients use `Fire` and\n`OnClientEvent`; servers use `FireClient`, the broadcast/collection fire\nmethods, and `OnServerEvent`. Calling an API from the wrong context throws.\n\nRequest/response packets are client-to-server only. The server binds one\nhandler and the client invokes it with `Fire`:\n\n```lua\nlocal GetItem = Sequena.Define({ Name = \"Inventory/GetItem\" }, Data.U32)\n    :SetRequestResponse(Data.String)\n\n-- Server\nGetItem:BindServerInvoke(function(Player, ItemId)\n    return \"Potion\"\nend)\n\n-- Client\nlocal ItemName = GetItem:Fire(42)\n```\n\n`TypedPacket` is also exported when an explicit packet contract annotation is\nuseful:\n\n```lua\nlocal Packet: Sequena.TypedPacket<(number, string)> = Sequena.Define({\n    Name = \"Inventory/Updated\",\n}, Data.U32, Data.String)\n```\n\n`Struct` accepts a keyed schema and infers the complete payload table:\n\n```lua\nlocal Item = Data.Struct({\n    Id = Data.U32,\n    Name = Data.String,\n})\n```\n\nKeyed struct fields are serialized in sorted key order. Use `OrderedStruct`\nwhen the wire order must be explicit; `Data.Field` retains each literal field\nname so the complete payload table is still inferred:\n\n```lua\nlocal OrderedItem = Data.OrderedStruct({\n    Data.Field(\"Id\", Data.U32),\n    Data.Field(\"Name\", Data.String),\n})\n```\n\n`Or` accepts between 2 and 25 schema options and infers their Luau union.\nSequena+ writes a one-byte option tag followed by the matching payload:\n\n```lua\nlocal StringOrNumber = Data.Or(Data.String, Data.F32)\n-- Descriptor<string | number>\n```\n\n`And` combines between 2 and 25 `Struct` or `OrderedStruct` schemas with\ndistinct field names and infers their Luau intersection:\n\n```lua\nlocal Item = Data.And(\n    Data.Struct({ Id = Data.U32 }),\n    Data.Struct({ Name = Data.String })\n)\n-- Descriptor<{ Id: number } & { Name: string }>\n```\n\n`Define` carries all positional schema fields through a generic type pack, so\nthere is no builder-specific inference or arity limit. Runtime schemas remain\nunchanged; the generic typing improves editor and type-checker feedback.\n","readmeTruncated":false}