# JPSPlus

JPSPlus is a high-performance **2D grid pathfinding** library for Roblox based on **Jump Point Search Plus (JPS+)** algorithm. It preprocesses static maps to enable very fast A* queries by “jumping” between critical nodes while preserving **optimal** paths on uniform-cost grids.

**The Concept:**
Traditional **Jump Point Search (JPS)** was originally developed as a superior competitor to standard A* for 2D grids, designed to speed up search by "jumping" over redundant nodes rather than checking every neighbor. **JPS+** takes this evolution a step further by using **preprocessing** to pre-calculate these jump distances. This results in ultra-fast queries that maintain A*'s **optimality** but with significantly reduced runtime overhead on static maps.

## When to use
Best for:
- top-down / flat worlds
- maze/indoor navigation on a plane
- many repeated queries on mostly static maps

## When NOT to use
Avoid if:
- **dynamic maps:** If your map changes every few seconds (e.g., destructible terrain), the cost of repeatedly "baking" the map data outweighs the search speed benefits.
- **Weighted Terrain:** If you need movement penalties (e.g., "mud is slower than grass"), use standard A*. JPS relies on uniform costs to skip nodes safely.
- **complex 3D verticality:** This is strictly for 2D grids; it does not handle multi-floor navigation natively without logical separation.

## Limitations
- 2D grid navigation (X/Z plane); not a 3D navmesh
- Static or mostly-static obstacles (changing obstacles require rebuild or custom updates)
- Uniform movement costs (no weighted terrain without modification)


# rbx-wallstick
A system for sticking characters to surfaces within Roblox.

### Videos

https://github.com/user-attachments/assets/bd4efde2-9323-4db1-896c-6407263e458e

https://github.com/user-attachments/assets/2a0478de-6e1f-4676-b778-9709b9e3f18f

https://github.com/user-attachments/assets/c6d9a53d-f6c2-4924-9286-728e21b92ee8


# rbx-viewport-window

Huge shout-out to [EmilyBendsSpace](https://x.com/EmilyBendsSpace) as their work is instrumental in ViewportWindows.

ViewportWindow provides developers with the tools to use viewport frames much like you'd use a window in real life. You can look into them and see a different space that is contained in a viewport frame. This can be used to do some neat stuff like non euclidean geometry.

https://github.com/user-attachments/assets/82b6cc32-1532-4cbb-bde0-988699a1e150

https://github.com/user-attachments/assets/da55b279-e9dc-4900-b498-8ebd27a0f312

https://github.com/user-attachments/assets/5f8dc572-75f4-4446-8b6c-174d0a924f4e

This repository is split into two parts:
- `src` contains the code for ViewportWindow.
- `demo` contains a couple of examples for using ViewportWindow.

You can build the demo with:

rojo build demo.project.json --output demo.rbxl


[bufferize/releases]: https://github.com/EgoMoose/rbx-bufferize/releases
[bufferize/wally]: https://wally.run/package/egomoose/bufferize

[badges/github]: https://raw.githubusercontent.com/gist/cxmeel/0dbc95191f239b631c3874f4ccf114e2/raw/github.svg
[badges/wally]: https://raw.githubusercontent.com/gist/cxmeel/0dbc95191f239b631c3874f4ccf114e2/raw/wally.svg

# rbx-bufferize

[![Get it on Github][badges/github]][bufferize/releases] [![Get it on Wally][badges/wally]][bufferize/wally]

A tool to losslessly encode / decode roblox data types to buffers.

```luau
local mail = {
    email = "john.doe@email.com",
    street = "321 Road City Country",
    unit = 123,

local tbl = {
    name = "John Doe",
    age = 603,
    contact = mail,
    mail = mail,

local b: buffer = Bufferize.encode("Hello world!", 123, true, tbl)
print(Bufferize.decode(b)) -- "Hello world!", 123, true, tbl

## Instances

Since instances can be converted to roblox data types it's possible for Bufferize to encode and decode them. To help with this Bufferize contains two functions to help with this process.

```luau
local b = Bufferize.encode(Bufferize.serializeInstance(workspace.Baseplate))
local baseplateCopy = Bufferize.deserializeInstance(Bufferize.decode(b))

Sometimes properties are references to other instances (i.e. `ObjectValue.Value`). In order for a reference to be maintained it must be pointing to an instance that is also in the instance tree being serialized.

```luau

local objV = Instance.new("ObjectValue")
local folder = Instance.new("Folder")
folder.Parent = objV

objV.Value = folder
local b = Bufferize.encode(Bufferize.serializeInstance(folder))
local objVCopy = Bufferize.deserializeInstance(Bufferize.decode(b))
-- valid: objVCopy.Value == folderCopy

objV.Value = workspace.Terrain
local b = Bufferize.encode(Bufferize.serializeInstance(folder))
local objVCopy = Bufferize.deserializeInstance(Bufferize.decode(b))
-- not valid: objVCopy.Value == nil

## Custom Encoding

Bufferize attempts to store all data types losslessly by default. This is helpful if precision is important for you, but depending on your project it may not be needed. In order to remain flexible in this regard Bufferize supports the ability to define custom encodings for any specific data type (except tables).

```luau
local inHouseEncoder = Bufferize.custom()

-- CFrame override that stores rotation euler angles XYZ rounded to nearest degree
-- this is not lossless, but depending on your use case it may be good enough and it results
-- in a smaller buffer size
inHouseEncoder:override("CFrame", {
    read = function(b: buffer)
        local stream = Bufferize.stream(b)
        local x, y, z = stream:readf32(), stream:readf32(), stream:readf32()
        local rx, ry, rz = math.rad(stream:readi16()), math.rad(stream:readi16()), math.rad(stream:readi16())
        return CFrame.new(x, y, z) * CFrame.fromEulerAngles(rx, ry, rz, Enum.RotationOrder.XYZ)
    end,
    write = function(cf: CFrame)
        local stream = Bufferize.stream(buffer.create(0))
        local rx, ry, rz = cf:ToEulerAngles(Enum.RotationOrder.XYZ)
        stream:writef32(cf.X)
        stream:writef32(cf.Y)
        stream:writef32(cf.Z)
        stream:writei16(math.round(math.deg(rx)))
        stream:writei16(math.round(math.deg(ry)))
        stream:writei16(math.round(math.deg(rz)))
        return stream.b
    end,
})

local complexRotation = CFrame.new(0, 0, 0, 1, 2, 3, 4)
local lengthA = buffer.len(Bufferize.encode(complexRotation))
local lengthB = buffer.len(inHouseEncoder:encode(complexRotation))
print(lengthA > lengthB) -- true

## Versioning

Bufferize strictly adheres to [semantic versioning](https://semver.org/).

When a buffer is encoded the current version of bufferize is included. That way when a buffer is decoded it's possible to ensure we're not attempting to decode with an incompatible version of bufferize.

For example, say you used bufferize v1.0.0 to store data in a datastore and then v2.0.0 is released. If you tried to read the v1.0.0 data with v2.0.0 bufferize then you'd get an error.

This means in practice that when a major version of bufferize releases old data will not be compatible. When the minor or patch version changes you can decode your old data with the new version of bufferize, but you can't decode your new data with the old version.

## Supported DataTypes

| **DataType**                | **Supported** | **Overridable** |
|-----------------------------|---------------|-----------------|
| **nil**                     | ✔             | ✔               |
| **boolean**                 | ✔             | ✔               |
| **function**                | ⛔             | ⛔               |
| **number**                  | ✔             | ✔               |
| **string**                  | ✔             | ✔               |
| **buffer**                  | ✔             | ✔               |
| **table**                   | ✔             | ❌               |
| **userdata**                | ⛔             | ⛔               |
| **Axes**                    | ✔             | ✔               |
| **BrickColor**              | ✔             | ✔               |
| **CatalogSearchParams**     | ❌             | ❌               |
| **CFrame**                  | ✔             | ✔               |
| **Color3**                  | ✔             | ✔               |
| **ColorSequence**           | ✔             | ✔               |
| **ColorSequenceKeypoint**   | ✔             | ✔               |
| **Content**                 | ⛔             | ⛔               |
| **DockWidgetPluginGuiInfo** | ⛔             | ⛔               |
| **Enum**                    | ✔             | ✔               |
| **EnumItem**                | ✔             | ✔               |
| **Enums**                   | ✔             | ✔               |
| **Faces**                   | ✔             | ✔               |
| **FloatCurveKey**           | ✔             | ✔               |
| **Font**                    | ✔             | ✔               |
| **Instance**                | ❌             | ❌               |
| **NumberRange**             | ✔             | ✔               |
| **NumberSequence**          | ✔             | ✔               |
| **NumberSequenceKeypoint**  | ✔             | ✔               |
| **OverlapParams**           | ⛔             | ⛔               |
| **Path2DControlPoint**      | ✔             | ✔               |
| **PathWaypoint**            | ✔             | ✔               |
| **PhysicalProperties**      | ✔             | ✔               |
| **Random**                  | ⛔             | ⛔               |
| **Ray**                     | ✔             | ✔               |
| **RaycastParams**           | ⛔             | ⛔               |
| **RaycastResult**           | ⛔             | ⛔               |
| **RBXScriptConnection**     | ⛔             | ⛔               |
| **RBXScriptSignal**         | ⛔             | ⛔               |
| **Rect**                    | ✔             | ✔               |
| **Region3**                 | ✔             | ✔               |
| **Region3int16**            | ✔             | ✔               |
| **RotationCurveKey**        | ✔             | ✔               |
| **Secret**                  | ⛔             | ⛔               |
| **SharedTable**             | ❌             | ❌               |
| **TweenInfo**               | ✔             | ✔               |
| **UDim**                    | ✔             | ✔               |
| **UDim2**                   | ✔             | ✔               |
| **ValueCurveKey**           | ⛔             | ⛔               |
| **vector**                  | ✔             | ✔               |
| **Vector2**                 | ✔             | ✔               |
| **Vector2int16**            | ✔             | ✔               |
| **Vector3**                 | ✔             | ✔               |
| **Vector3int16**            | ✔             | ✔               |

✔ Implemented  | ❌ Unimplemented | ⛔ Never


# RbxShader
A robust, simple, and performant fragment shader engine, for everyone.

The shader engine can run virtually any shader program that operates on a per-pixel basis, just like those on [Shadertoy](https://www.shadertoy.com/). Porting these programs are relatively easy due to their code structuring being similar. If you wish to test the abilities of this engine or understand how to write shader programs with this engine, you can use [any of the give example shader programs provided](https://github.com/AnotherSubatomo/RbxShader/blob/main/Shaders/), which are also ports of pre-existing shader programs in Shadertoy 😊.

If you have an eye for possible optimizations, or how the shader could be better in any way, please feel free to contribute as **this project is open-source and is open for contribution.**

#### Features
1. Multithreading - shader program rendering is divided among an amount of worker threads, which is specified by the user. *For practicality, this amount can only be a multiple of four.*

2. Interlacing - this is a rendering technique that intentionally skips over the rendering of some amount of rows & columns per frame. It is employed to double the percieved frame rate but also boost performance as skipping reduces the amount of computations done per frame, increasing the likelyhood of the frame budget being satisfied, therefore reducing FPS decrease.

3. Partial re-implementation of *common* GLSL functions - a library containing some of the common graphics-related math operations is provided along the engine. [_Swizzling_](https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)) is not planned to be a feature of this library that is widely supported anytime in the future. As while it improves readability, the overhead from the additional function frame hurts overall performance.

4. Multiple shader buffer support (multipass) - a multipass system is provided by the engine; where the shader can go through function `bufferA`, `bufferB`, etc. before finally going through `mainImage`.

5. User input handling (mouse movement) - the mouses position within the shader's viewport is tracked every left-click on the viewport, and stops tracking when the button is let go or the mouse goes outside the viewport.

#### Features that are planned to be implemented:
- Texture channel sampling
- Frame interpolation (possible performance gains are yet to be evauated)

Read more about the engine through the [DevForum post](https://devforum.roblox.com/t/rbxshader-a-robust-shader-engine-for-everyone/2965460).

Learn more about the engine via the a [DevForum tutorial post](https://devforum.roblox.com/t/rbxshader-tutorial/2965555) or [documentations](docs/DOCUMENTATION.md).

## Getting Started
To build the place from scratch, use:

```bash
rojo build -o "RbxShader.rbxlx"

Next, open `RbxShader.rbxlx` in Roblox Studio and start the Rojo server:

```bash
rojo serve

For more help, check out [the Rojo documentation](https://rojo.space/docs).


# RbxObservers

A collection of observer utility functions.

## Installation

### Wally

Add `sleitnick/observers` to dependencies list:
```toml
[package]
name = "your_name/your_project"
version = "0.1.0"
registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"

[dependencies]
Observers = "sleitnick/observers@^0.4.0"

### roblox-ts

Add `@rbxts/observers` to your `package.json` dependencies list, or run the npm install command:

```json
    "dependencies": {
        "@rbxts/observers": "^0.4.0"

```sh
npm i --save @rbxts/observers


InfiniteMath is a module that allows you to surpass the double-precision floating-point number limit of `10^308`.

Here's the [installation](https://kdudedev.github.io/InfiniteMath/docs/Installation) page, an in-depth [explanation](https://kdudedev.github.io/InfiniteMath/docs/Explanation) of the module, and API [documentation](https://kdudedev.github.io/InfiniteMath/api/InfiniteMath).

Here's the [DevForum](https://devforum.roblox.com/t/infinitemath-go-above-103081e308/2182434) post of the module. If you use InfiniteMath in your game, send it to me on Discord `Kdude#1774` or reply to the post with your game and I'll add it to the DevForum post!

Here is an [uncopylocked game](https://www.roblox.com/games/12427031634/InfiniteMath-Demonstration) that uses InfiniteMath. It's a simple idle game but it gets the point across, and here is a [video](https://www.youtube.com/watch?v=n2ReZtRgCmw) showing off that game.


# What is this?

InfiniteMath is a module that allows you to surpass the double-precision floating-point number limit which about:

> -10^308 to 10^308

This is normally perfectly fine for games, but sometimes you might want to go past that limit, even just a little bit. InfiniteMath allows you to have practically infinite numbers. InfiniteMath stores 2 numbers instead of 1 in a clever way to get around the limit.

InfiniteMath's limit is about:

> -10^^308 to 10^^308

In simpler terms, Roblox's normal limit is 1 with 308 zeros. InfiniteMath's limit is 1 with 10^308 zeros.

Fun fact, a googolplex is 10^100^100, which means you can use a googolplex with InfiniteMath.

Numbers constructed from InfiniteMath supports arithmetic operators `(+, -, *, /, ^, %)` with constructed numbers and normal numbers, and comparison operators `(<, >, <=, >=, ==, ~=)` with other constructed numbers. InfiniteMath also has support for OrderedDataStores.

There are also suffixes up to `1e+12000`, after that all numbers will display scientific notation. If you want to see all the suffixes, here's a [google doc](https://docs.google.com/document/d/e/2PACX-1vTB2zhx8PCdu5HpV5kwqmNx8BV9RCv44qZaljlTb0Mm0nkzwMQ2cI6aupxrNktrlylsp-QnbES-XteP/pub) with them.

If you have a list that goes higher than `1e+12000` (Trillinovenonagintanongentillion/TRNNA), by all means share it with me, I'd love to see it.

# How does it work?

A normal number in Roblox looks like this:

> 1

Now if we were to convert that to InfiniteMath, it would look like:

> {1, 0}

To explain, we can construct a table out of a number by taking the coefficient and the exponent of a number.

Lets say we want to use `1000` with the module, we take the coefficient (1) and the exponent, which the amount of zeros (3) and put them in a table:

> {1, 3}

Now if we did something like `{1, 3} + {1, 2}`, we would get:

> {1.1, 3}

This gives us `1100`. And since we're not using numbers, we can go above the limit. For example, `{1, 1000}` is equal to 1 with 1000 zeros, or 1 Untrigintatrecentillion. We can continue all the way up until reaching `1e+308` zeros, which would look like:

> {1, 1e+308}

And if we tried to display that as a number, it would return `1e+1.e+308`, aka 1 with `1 * 10^308` zeros. This is practically infinite, and if you ever have a use for going higher I will be very surprised.


# Datastore Implementation

InfiniteMath uses metatables, meaning numbers created using it can't be saved in a datastore. If you do save an InfiniteMath number in a datastore, it will lose its metamethods which means no operations, comparisons, etc.

The solution is to recreate the number when loading it using `.new()`

    local Money = InfiniteMath.new(1)

    Data.Money = Money

When you want to use the number again, simply convert it back to an InfiniteMath number

    local Money = InfiniteMath.new(Data.Money)


# @rbxts/profile-store

## Installation:

`npm i @rbxts/profile-store`

## Documentation

See [MadStudioRoblox/ProfileStore](https://github.com/MadStudioRoblox/ProfileStore)


# RBXConnectionManager

This is our first open-source release. Please add a ⭐ if you like the idea of this project or if you like to use it.

Roblox Developer Forum Thread: https://devforum.roblox.com/t/3503750

Consider joining our community aswell! https://discord.gg/8ed3W53kHv/ to see progress on our very advanced projects and enjoy early-access benefits while you still can!

## Overview
RBXConnectionManager is a lightweight and efficient module for managing `RBXScriptConnection` objects in Roblox. It allows for easy connection handling, automatic cleanup, and optional event monitoring.

## Features
- **Efficient Connection Management**: Easily create, store, and disconnect connections by name.
- **Automatic Cleanup**: Removes player-specific connections when a player leaves (server-side feature) -> the player's UserId must be in the connection name.
- **Batch Disconnection**: Disconnect all connections or those within a specific group.
- **Monitoring**: Logs and displays event calls along with timestamps.
- **Self-Destruction**: Provides a method to completely clean up the manager.

## Installation
1. Add `RBXConnectionManager.luau` to your Roblox project.
2. Require the module where needed:
   ```lua
   local RBXConnectionManager = require(path.to.rbxconnectionmanager)

## Usage

### Creating an Instance
```lua
local connectionManager = RBXConnectionManager.new()

### Adding Connections
```lua
local myEvent = game.ReplicatedStorage.SomeRemoteEvent

connectionManager:Connect("ExampleConnection", myEvent.OnServerEvent, function(player, data)
    print("Event triggered by:", player.Name, "with data:", data)
end, true) -- Enable monitoring

### Disconnecting a Specific Connection
```lua
connectionManager:Disconnect("ExampleConnection")

### Disconnecting All Connections in a Group
This will disconnect all events that contain the provided string in their name.
```lua
connectionManager:DisconnectAllInGroup("OnCarShowClicked")

### Disconnecting All Connections
```lua
connectionManager:DisconnectAll()

### Retrieving Monitoring Logs
```lua
connectionManager:GetAllMonitoringData()

### Destroying the Manager
This will also disconnect all existing connections (like connectionManager:DisconnectAll() does)
```lua
connectionManager:Destroy()

### Using AutoDisconnect
This will disconnect all connections in group (group_name, like connectionManager:DisconnectAllInGroup) when an RBXScriptConnection (event) is fired
```lua
connectionManager:AddAutoDisconnect(group_name, event)

### Basic Example (Server-side Car Show Handler)

```lua
local Players = game:GetService("Players")
local RBXConnectionManager = require(game.ServerScriptService.rbxconnectionmanager)

-- Create a new connection manager
local connectionManager = RBXConnectionManager.new()

-- Example RemoteEvent
local remoteEvent = game.ReplicatedStorage.SomeRemoteEvent

-- Connect an event with automatic tracking
Players.PlayerAdded:Connect(function(playerObj)
    local userid = playerObj.UserId
    connectionManager:Connect("OnCarShowClicked_" .. tostring(userid), remoteEvent.OnServerEvent, function(triggeringPlayer, data)
        print(triggeringPlayer.Name .. " triggered the event with data:", data)
        warn("Send " .. triggeringPlayer.Name .. " congratulations about " .. triggeringPlayer.Name .. " clicking on his car show")
    end, true) -- Enable monitoring
end)

## Notes
- On the **server-side**, connections linked to a player will be automatically removed when they leave.
- Monitoring can be useful for debugging event calls, but it may have performance implications if used excessively.
- The module is designed to work efficiently in both **server-side** and **client-side** scripts.

## Open-source
This module is open-source and free to use in any Roblox project. Contributions and improvements are welcome!


## :warning: No Longer Maintained :warning:

Knit has been archived and will no longer receive updates.

Please [read here](/ARCHIVAL.md) for more information.

# Knit

Knit is a lightweight framework for Roblox that simplifies communication between core parts of your game and seamlessly bridges the gap between the server and the client.

Read the [documentation](https://sleitnick.github.io/Knit/) for more info.

## Install

Installing Knit is very simple. Just drop the module into ReplicatedStorage. Knit can also be used within a Rojo project.

**Roblox Studio workflow:**

1. Get [Knit](https://www.roblox.com/library/5530714855/Knit) from the Roblox library.
1. Place Knit directly within ReplicatedStorage.

**Wally & Rojo workflow:**

1. Add Knit as a Wally dependency (e.g. `Knit = "sleitnick/knit@^1"`)
1. Use Rojo to point the Wally packages to ReplicatedStorage.

## Basic Usage

The core usage of Knit is the same from the server and the client. The general pattern is to create a single script on the server and a single script on the client. These scripts will load Knit, create services/controllers, and then start Knit.

The most basic usage would look as such:

```lua
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

Knit.Start():catch(warn)
-- Knit.Start() returns a Promise, so we are catching any errors and feeding it to the built-in 'warn' function
-- You could also chain 'await()' to the end to yield until the whole sequence is completed:
--    Knit.Start():catch(warn):await()

That would be the necessary code on both the server and the client. However, nothing interesting is going to happen. Let's dive into some more examples.

### A Simple Service

A service is simply a structure that _serves_ some specific purpose. For instance, a game might have a MoneyService, which manages in-game currency for players. Let's look at a simple example:

```lua
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

-- Create the service:
local MoneyService = Knit.CreateService {
    Name = "MoneyService",

-- Add some methods to the service:

function MoneyService:GetMoney(player)
    -- Do some sort of data fetch
    local money = someDataStore:GetAsync("money")
    return money
end

function MoneyService:GiveMoney(player, amount)
    -- Do some sort of data fetch
    local money = self:GetMoney(player)
    money += amount
    someDataStore:SetAsync("money", money)
end

Knit.Start():catch(warn)

Now we have a little MoneyService that can get and give money to a player. However, only the server can use this at the moment. What if we want clients to fetch how much money they have? To do this, we have to create some client-side code to consume our service. We _could_ create a controller, but it's not necessary for this example.

First, we need to expose a method to the client. We can do this by writing methods on the service's Client table:

```lua
-- Money service on the server
...
function MoneyService.Client:GetMoney(player)
    -- We already wrote this method, so we can just call the other one.
    -- 'self.Server' will reference back to the root MoneyService.
    return self.Server:GetMoney(player)
end
...

We can write client-side code to fetch money from the service:

```lua
-- Client-side code
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)
Knit.Start():catch(warn):await()

local MoneyService = Knit.GetService("MoneyService")

MoneyService:GetMoney():andThen(function(money)
    print(money)
end)

Under the hood, Knit is creating a RemoteFunction bound to the service's GetMoney method. Knit keeps RemoteFunctions and RemoteEvents out of the way so that developers can focus on writing code and not building networking infrastructure.


# Warp

# A rapidly-fast & powerful networking library.

## Why Warp

### ⚡ Performance
Warp is rapidly-fast with much less bandwidth compared to native.

### 🍃 Compact
Warp is a simple, efficient & lightweight library.

### 📊 Dynamic
Warp is dynamic by default. It serializes and deserializes data dynamically without requiring a user-defined schema, although schema support is available as an option.

### 🔎 Typing
Warp written with strictly-typed.

Visit Warp [documentation](https://imezx.github.io/Warp)


# Warp 1.1 pre-release

The public main of the Warp library.

WARNING

This version (1.1.x) is not backward compatible with 1.0.x.

## `.Server` server side

Get the Server operation for server-side.

lua

    -- Server
    local Server = Warp.Server()

## `.Client` client side

Get the Client operation for client-side.

lua

    -- Client
    local Client = Warp.Client()

## `.Buffer` universal

Get the Buffer util for schema definition.

lua

    -- Universal (Server & Client)
    local Buffer = Warp.Buffer()
    local schema = Buffer.Schema


# Overview

Warp is a powerful networking library for Roblox that comes with rapidly-fast performance and efficient with Typing to any-scale games.

## Why Warp

### ⚡ Performance

Warp is rapidly-fast with much less bandwidth compared to native.

### 🍃 Compact

Warp is a simple, efficient & lightweight library.

### 📊 Dynamic

Warp is dynamic by default. It serializes and deserializes data dynamically without requiring a user-defined schema, although schema support is available as an option.

### 🔎 Typing

Warp written with strictly-typed.


# Warp 1.0 deprecated

The public main of the Warp library.

## `.Server` server side

Create a new event for Server-Side

lua

    -- Server
    local Event1 = Warp.Server("Event1")

## `.Client` client side

Create a new event for Client-Side.

lua

    -- Client
    local Event1 = Warp.Client("Event1")


# Client 1.1

For Client-sided operations.

## Getting the Client Object

lua

    local Client = Warp.Client()

## `.awaitReady` yield

Yields the current thread until the client has successfully initialized and synchronized with the server's replication data (identifier).

INFO

Its optionally, but highly recommended to call this before firing or connecting to any events to ensure the network is fully ready.

VariableExample

luau

    () -> ()

luau

    local Client = Warp.Client()

    -- wait for the client to be fully initialized
    Client.awaitReady()

    print("Client is now ready to send and receive events! :D")

## `.Connect`

Connect to an event to receive incoming data from the server.

VariableExample

luau

    (
        remoteName: string,
        fn: (...any) -> ...any
    ) -> Connection

luau

    local connection = Client.Connect("ServerNotify", function(message, sender)
        print(`Server message from {sender}: {message}`)
    end)
    print(connection.Connected)

## `.Once`

Similar to `:Connect` but automatically disconnects after the first firing.

VariableExample

luau

    (
        remoteName: string,
        fn: (...any) -> ...any
    ) -> Connection

luau

    Client.Once("WelcomeMessage", function(welcomeText)
        print(`Welcome: {welcomeText}`)
    end)

## `.Wait` yield

Wait for an event to be triggered.

VariableExample

luau

    (
        remoteName: string
    ) -> (number, ...any)

luau

    local elapsed, message = Client.Wait("ServerMessage")
    print(`Received message after {elapsed} seconds: {message}`)

## `.Disconnect`

Disconnect the event connection.

VariableExample

luau

    ()

luau

    local connection = Client.Connect("ServerNotify", function(message, sender)
        print(`Server message from {sender}: {message}`)
        -- Disconnect the connection
        connection:Disconnect()
    end)
    print(Connection.Connected)

## `.DisconnectAll`

Disconnect all connections for a specific event.

VariableExample

luau

    (
        remoteName: string
    )

luau

    Client.DisconnectAll("ServerNotify")

## `.Destroy`

Disconnect all connections and remove the event.

VariableExample

luau

    (
        remoteName: string
    )

luau

    Client.Destroy("ServerNotify")

## `.Fire`

Fire an event to the server.

VariableExample

luau

    (
        remoteName: string,
        reliable: boolean,
        ...: any
    )

luau

    -- (TCP) Reliable event (guaranteed delivery)
    Client.Fire("PlayerAction", true, "jump", playerPosition)

    -- (UDP) Unreliable event (faster but not guaranteed)
    Client.Fire("PositionUpdate", false, currentPosition)

## `.Invoke` yield

Invoke the server with timeout support.

VariableExample

luau

    (
        remoteName: string,
        timeout: number?,
        ...: any
    ) -> ...any

luau

    local Client = Warp.Client()
    local response = Client.Invoke("RequestData", 3, "playerStats")
    if response then
        print("Server responded:", response)
    else
        print("Request timed out")
    end

WARNING

This function is yielded. Returns `nil` if timeout occurs.

## `.useSchema`

Define a schema for strict data packing on a specific event.

VariableExample

luau

    (
        remoteName: string,
        schema: Buffer.SchemaType
    )

luau

    local Client = Warp.Client()

    -- Define a schema for position updates
    local positionSchema = Client.Schema.struct({
        x = Client.Schema.f32,
        y = Client.Schema.f32,
        z = Client.Schema.f32,
        timestamp = Client.Schema.u32
    })
    -- Define a schema for data updates
    local dataSchema = Client.Schema.struct({
        Coins = Client.Schema.u32,
        Level = Client.Schema.u8,
        Inventory = Client.Schema.array(Client.Schema.u32),
        Settings = Client.Schema.struct({
            VFX = Client.Schema.boolean,
            Volume = Client.Schema.f32,
            Language = Client.Schema.string,
        })
    })

    -- Now this event will use the schema
    Client.useSchema("DataReplication", dataSchema)
    Client.useSchema("PositionUpdate", positionSchema)
    Client.Connect("PositionUpdate", function(x, y, z, timestamp)
        -- Data is automatically deserialized according to schema
        updatePlayerPosition(x, y, z)
    end)

## `.Schema`

Access to Buffer.Schema for creating data schemas.


# Buffer module

For efficient data serialization and schema definition with optimized packing.

## Getting the Buffer Object

lua

    local Buffer = Warp.Buffer()

## Schema System v1.1

Define strict data schemas for optimized serialization and type safety.

### Available Schema Types

lua

        -- Basic types
        "boolean",
        "string",
        "nil",

        -- Numeric types
        "u8", -- usigned-int
        "u16",
        "u32",
        "i8", -- signed-int
        "i16",
        "i32",
        "f16", -- floating-point
        "f32",
        "f64",

        -- Roblox types
        "buffer"
        "vector2", -- f16
        "vector3", -- f16
        "cframe", -- f32 & f16
        "color3", -- u8
        "color3f16",
        "instance",

        -- other types
        "optional",
        "array",
        "map",
        "struct",

## Custom Datatypes

### `.custom_datatype`

VariableExample

luau

    (
        name: string,
        object: { any },
        writer: (w: Writer, v: any) -> (),
        reader: (b: buffer, c: number, refs: { Instance }?) -> (buffer, number))
    )

luau

    local Buffer = Warp.Buffer()

    -- # this custom datatype must be registered on both server & client side
    Buffer.Schema.custom_datatype("u64", {}, function(w: Buffer.Writer, value: any) -- just for reference
        -- writing u64 logics here
    end, function(b: buffer, cursor: number, refs)
        -- reading u64 logics here
        return b, cursor
    end)

    local DataSchema = Buffer.Schema.struct({
        LongInteger = Buffer.Schema.u64, -- use the custom datatype
    })

## Writer and Reader Functions

### `.createWriter`

Create a new buffer writer for serializing data.

VariableExample

luau

    (
        capacity: number? -- Optional initial capacity (default: 64)
    ): Writer

luau

    local Buffer = Warp.Buffer()
    local writer = Buffer.createWriter(256) -- Pre-allocate 256 bytes

### `.build`

Build the final buffer for transmission.

VariableExample

luau

    (
        writer: Writer
    ): buffer -- Returns buffer

luau

    local Buffer = Warp.Buffer()
    local writer = Buffer.createWriter()

    -- Write some data
    Buffer.packValue(writer, "Hello World")
    Buffer.packValue(writer, 12345)

    -- Build final buffer
    local finalBuffer = Buffer.build(writer)
    print(buffer.len(finalBuffer))

### `.buildWithRefs`

Build the final buffer with instance references for transmission.

VariableExample

luau

    (
        writer: Writer
    ): (buffer, { Instance }?) -- Returns buffer and optional instance references

luau

    local Buffer = Warp.Buffer()
    local writer = Buffer.createWriter()

    -- Write some data with instances
    Buffer.packValue(writer, workspace.Part)
    Buffer.packValue(writer, game.Players.LocalPlayer)

    -- Build final buffer
    local finalBuffer, refs = Buffer.buildWithRefs(writer)
    print(buffer.len(finalBuffer), refs)

### `.reset`

Reset a writer for reuse, clearing all data.

VariableExample

luau

    (
        writer: Writer
    )

luau

    local Buffer = Warp.Buffer()
    local writer = Buffer.createWriter()

    -- Use writer for first batch
    Buffer.writeEvents(writer, events1)
    local buffer1 = Buffer.build(writer)

    -- Reset and reuse for second batch
    Buffer.reset(writer)
    Buffer.writeEvents(writer, events2)
    local buffer2 = Buffer.build(writer)


# Server 1.1

For Server-sided operations.

## Getting the Server Object

lua

    local Server = Warp.Server()

## `.reg_namespaces`

Register namespaces to ensure all of the namespaces is being registered earlier on the server to prevent any unexpected issues on the client.

INFO

this is optional and conditional, you may have to use this if you had a problem with identifier namespace on client.

VariableExample

luau

    (
        namespaces: { string },
    ) -> Connection

luau

    Server.reg_namespaces({
        "ServerNotify",
        "ServerMessage",
        "WelcomeMessage",
        "Broadcast",
        "DataReplication",
        "RequestData",
        "Update"
    })

## `.Connect`

Connect to an event to receive incoming data from clients.

VariableExample

luau

    (
        remoteName: string,
        fn: (player: Player, ...any) -> ...any
    ) -> Connection

luau

    local connection = Server.Connect("ServerNotify", function(player, message)
        print(`Client message from {player}: {message}`)
    end)
    print(connection.Connected)

## `.Once`

Similar to `:Connect` but automatically disconnects after the first firing.

VariableExample

luau

    (
        remoteName: string,
        fn: (player: Player, ...any) -> ...any
    ) -> Connection

luau

    Server.Once("WelcomeMessage", function(welcomeText)
        print(`Welcome: {welcomeText}`)
    end)

## `.Wait` yield

Wait for an event to be triggered.

VariableExample

luau

    (
        remoteName: string
    ) -> (number, ...any)

luau

    local elapsed, message = Server.Wait("ServerMessage")
    print(`Received message after {elapsed} seconds: {message}`)

## `.DisconnectAll`

Disconnect all connections for a specific event.

VariableExample

luau

    (
        remoteName: string
    )

luau

    Server.DisconnectAll("ServerNotify")

## `.Destroy`

Disconnect all connections and remove the event.

VariableExample

luau

    (
        remoteName: string
    )

luau

    Server.Destroy("ServerNotify")

## `.Fire`

Fire an event to a specific player.

VariableExample

luau

    (
        remoteName: string,
        reliable: boolean,
        player: Player,
        ...: any
    )

luau

    Server.Fire("ServerNotify", true, player, "Hello from server!")

## `.Fires`

Fire an event to all connected players.

VariableExample

luau

    (
        remoteName: string,
        reliable: boolean,
        ...: any
    )

luau

    Server.Fires("Broadcast", true, "Server announcement!")

## `.FireExcept`

Fire an event to all players except specified ones.

VariableExample

luau

    (
        remoteName: string,
        reliable: boolean,
        except: { Player },
        ...: any
    )

luau

    local excludedPlayers = { player1, player2 }
    Server.FireExcept("Update", true, excludedPlayers, "Game update")

## `.Invoke` yield

Invoke a client with timeout support.

VariableExample

luau

    (
        remoteName: string,
        player: Player,
        timeout: number?,
        ...: any
    ) -> ...any

luau

    local response = Server.Invoke("RequestData", player, 3, "userInfo")
    if response then
        print("Client responded:", response)
    else
        print("Request timed out")
    end

WARNING

This function is yielded. Returns `nil` if timeout occurs.

## `.useSchema`

Define a schema for strict data packing on a specific event.

VariableExample

luau

    (
        remoteName: string,
        schema: Buffer.SchemaType
    )

luau

    local Server = Warp.Server()

    local dataSchema = Server.Schema.struct({
        Coins = Server.Schema.u32,
        Level = Server.Schema.u8,
        Inventory = Server.Schema.array(Server.Schema.u32),
        Settings = Server.Schema.struct({
            VFX = Server.Schema.boolean,
            Volume = Server.Schema.f32,
            Language = Server.Schema.string,
        })
    })

    Server.useSchema("DataReplication", dataSchema)

## `.Schema`

Access to Buffer.Schema for creating data schemas.


# Example 1.1

Let's try and play something with Warp!

SchemasServerClient

luau

    local Schema = require(path.to.warp).Buffer.Schema

    return {
        Example = Schema.array(Schema.string),
        Ping = Schema.string,
        Pong = Schema.string,
        PingAll = Schema.string,

luau

    local Warp = require(path.to.warp).Server()
    local Schemas = require(path.to.schemas)

    -- Use schemas
    for eventName, schema in Schemas do
        Warp.useSchema(eventName, schema)
    end

    Warp.Connect("Example", function(player, arg)
        print(table.unpack(arg))
        return "Hey!"
    end)
    Warp.Connect("Ping", function(player, ping)
        if ping then
            print("PING!")
            Warp.Fire("Pong", true, player, "pong!") -- Fire to spesific player through reliable event
            Warp.Fire("PingAll", true, "ey!") -- Fire to all clients through reliable event
        end
    end)

luau

    local Players = game:GetService("Players")
    local Warp = require(path.to.warp).Client()
    local Schemas = require(path.to.schemas)

    -- Use schemas
    for eventName, schema in Schemas do
        Warp.useSchema(eventName, schema)
    end

    -- Connect the events
    local connection1
    connection1 = Warp.Connect("Pong", function(pong: boolean) -- we store the connection so we can disconnect it later
        if pong then
            print("PONG!")
        end
    end)
    Warp.Connect("PingAll", function(isPing: boolean)
        if isPing then
            print("I GET PINGED!")
        end
    end)

    task.wait(3) -- lets wait a few seconds, let the server do the things first!

    -- Try request a event from server!
    print(Warp.Invoke("Example", 1, { "Hello!", `this is from: @{Players.LocalPlayer.Name}` }))
    -- Do a ping & pong to server!
    Warp.Fire("Ping", true, "ping!") -- we send through reliable event

    task.wait(1) -- lets wait for a second!

    -- Disconnect All the events
    connection1:Disconnect()
    -- or just disconnect spesific connection
    Warp.DisconnectAll("PingAll")

    -- Destroying/Deleting a Event?
    Warp.Destroy("Pong")


# Getting Started 1.1

### `Installation`

First, you have to require the Warp module.

lua

    local Warp = require(path.to.module)

Then, you should do `.Server` or `.Client`

lua

    local Server = Warp.Server() --> for Server-side only
    local Client = Warp.Client() --> for Client-side only

### `Basic Usage`

Firing event everytime player join

lua

    local Players = game:GetService("Players")

    Players.PlayerAdded:Connect(function(player: Player)
        Server.Fire("MessageEvent", true, player, "Welcome!")
    end)

Add a listener (works for both `.Invoke` & `.Fire`)

lua

    local connection = Server.Connect("Ping", function(player: Player)
        return "Pong"
    end)
    print(connection.Connected)
    -- connection:Disconnect()

Send or Request a event

lua

    -- Reliable-RemoteEvent
    Client.Fire("test", true, "hey")
    -- Unreliable-RemoteEvent
    Client.Fire("test", false, "hello from client!!")
    -- Invoke
    local response = Client.Invoke("Ping")
    if not response then
        warn("Server didn't ping back :(")
        return
    end
    print(response, "from Server!")


# Installation

## wally

wally.toml

toml

    [dependencies]
    warp = "imezx/warp@1.1.0"

## pesde

pesde.tomlcli

toml

    [dependencies]
    warp = { name = "eternitydev/warp", version = "^1.1.0" }

bash

    pesde add eternitydev/warp

## Roblox Studio

  1. Get the `.rbxm` file from the [github](https://github.com/imezx/Warp)
  2. Import the `.rbxm` file into roblox studio manually and Done!


# Server event

For Server-sided

## `.Server` yield

Create new Warp event.

VariableExample

luau

    (
        Identifier: string,
        rateLimit: {
            maxEntrance: number?,
            interval: number?,
        }?
    )

luau

    local Remote = Warp.Server("Remote")

## `.fromServerArray` yield

Create new Warp events with array.

VariableExample

luau

    (
        { any }
    )

luau

    local Events = Warp.fromServerArray({
        ["Remote1"] = {
            rateLimit = {
                maxEntrance: 50,
                interval: 1,
        }, -- with rateLimit configuration
        "Remote2", -- without rateLimit configuration
        ["Remote3"] = {
            rateLimit = {
                maxEntrance: 10,
        }, -- with rateLimit configuration
    })

    -- Usage
    Events.Remote1:Connect(function(player, ...) end)
    Events.Remote2:Connect(function(player, ...) end)
    Events.Remote3:Connect(function(player, ...) end)

## `:Connect`

Connect event to receive incoming from client way.

VariableExample

luau

    (
        player: Player,
        callback: (...any) -> ()
    ): string

luau

    Remote:Connect(function(player, ...)
        print(player, ...)
    end)

## `:Once`

This function likely `:Connect` but it disconnect the event once it fired.

VariableExample

luau

    (
        player: Player,
        callback: (...any) -> ()
    )

luau

    Remote:Once(function(player, ...)
        print(player, ...)
    end)

## `:Disconnect`

Disconnect the event connection.

VariableExample

luau

    (
        key: string
    ): boolean

luau

    local connection = Remote:Connect(function(player, ...) end) -- store the key

    Remote:Disconnect(connection)

## `:DisconnectAll`

Disconnect All the event connection.

luau

    Remote:DisconnectAll()

## `:Fire`

Fire the event to a client.

VariableExample

luau

    (
        reliable: boolean,
        player: Player,
        ...: any
    )

luau

    Remote:Fire(true, player, "Hello World!")

## `:Fires` Server Only

Fire the event to all clients.

VariableExample

luau

    (
        reliable: boolean,
        ...: any
    )

luau

    Remote:Fires(true, "Hello World!")

## `:FireExcept` Server Only

Fire the event to all clients but except a players.

VariableExample

luau

    (
        reliable: boolean,
        except: { Player },
        ...: any
    )

luau

    Remote:FireExcept(true, { Players.Eternity_Devs, Players.Player2 }, "Hello World!") -- this will sent to all players except { Players.Eternity_Devs, Players.Player2 }.

## `:Invoke` yield

Semiliar to `:InvokeClient`, but it have timeout system that not exists on `RemoteFunction.InvokeClient`.

VariableExample

luau

    (
        timeout: number,
        player: Player,
        ...: any
    ) -> (...any)

luau

    local Request = Remote:Invoke(2, player, "Hello World!")

WARNING

This function is yielded, once it timeout it will return nil.

## `:Wait` yield

Wait the event being triggered.

lua

    Remote:Wait() -- :Wait return number value

WARNING

This function is yielded, Invoke might also ping this one and also causing error.

## `:Destroy`

Disconnect all connection of event and remove the event from Warp.

lua

    Remote:Destroy()


# Signal utilities

A alternative of BindableEvent.

## `.Signal`

Create new Signal.

VariableExample

luau

    (
        Identifier: string
    )

luau

    local Signal1 = Warp.Signal("Signal1")

## `.fromSignalArray`

Create new Signal.

VariableExample

luau

    (
        { string }
    )

luau

    local Signals = Warp.fromSignalArray({"Signal1", "Signal2"})
    Signals.Signal1:Connect(function(...) end)
    Signals.Signal2:Connect(function(...) end)

## `:Connect`

VariableExample

luau

    (
        callback: (...any) -> ()
    )

luau

    Signal1:Connect(function(...)
        print(...)
    end)

## `:Once`

This function likely `:Connect` but it disconnect the signal once it fired.

VariableExample

luau

    (
        callback: (...any) -> ()
    )

luau

    Signal1:Once(function(...)
        print(...)
    end)

## `:Disconnect`

Disconnect the signal connection.

VariableExample

luau

    (
        key: string
    )

luau

    local connection = Signal1:Connect(function(...) end) -- store the key

    Signal1:Disconnect(connection)

WARNING

This requires `key` to disconnect a signal connection.

## `:DisconnectAll`

Disconnect All signal connections.

luau

    Signal1:DisconnectAll()

## `:Fire`

Fire the signal (Immediate)

VariableExample

luau

    (
        ...: any
    )

luau

    Signal1:Fire("Hello World!")

## `:DeferFire`

Fire the signal (Deferred)

VariableExample

luau

    (
        ...: any
    )

luau

    Signal1:Fire("Hello World!")

WARNING

This uses `pcall`, which means it never error (safe-mode, sacrificed debugging), But gains performance here `(upto 5x faster)`.

## `:FireTo`

Fire to other signal, this uses `:Fire`.

VariableExample

luau

    (
        signal: string,
        ...: any
    )

luau

    Signals.Signal1:FireTo("Signal2", "Hello World!")

WARNING

This requires `key`.

## `:Invoke` yield

VariableExample

luau

    (
        key: string,
        ...: any
    ) -> (...any)

luau

    local connection = Signal1:Conenct(function(...) return "hey!" end)
    local Request = Signal1:Invoke(connection, "Hello World!")

## `:InvokeTo` yield

this use `:Invoke`.

VariableExample

luau

    (
        signal: string,
        key: string,
        ...: any
    ) -> (...any)

luau

    local connection2 = Signals.Signal2:Conenct(function(...) return "hey!" end)
    local Request = Signals.Signal1:Invoke("Signal2", connection2, "Hello World!")

WARNING

This requires `key`.

## `:Wait` yield

Wait the signal get triggered.

lua

    Signal1:Wait() -- return number (time)

WARNING

This function is yielded

## `:Destroy`

Disconnect all connection of signal and remove the signal from Signals

lua

    Signal1:Destroy()


# Rate Limit feature

Ratelimit is one of most useful feature.

( Configured on Server only and For Client )

## `Setup`

When creating a event on Server, you can add second argument (optional) as table `rateLimit` to limit the number of times the event can be called and the interval for reset the counter on client-side.

ServerClient

luau

    -- Server
    -- Let's make the event have ratelimit with max 50 entrance for 2 seconds.
    local Remote = Warp.Server("Remote1", {
        rateLimit = {
            maxEntrance = 50, -- maximum 50 fires.
            interval = 2, -- 2 seconds
    })
    -- Now the Event RateLimit is configured, and ready to use.
    -- No need anything to adds on client side.

luau

    -- Client
    local Remote = Warp.Client("Remote1") -- Yields, retreive rateLimit configuration.
    -- The Event will automatic it self for retreiving the rate limit configuration from the server.


# Client event

For Client-sided

## `.Client` yield

Create new Warp event.

VariableExample

luau

    (
        Identifier: string
    )

luau

    local Remote = Warp.Client("Remote")

## `.fromClientArray` yield

Create new Warp events with array.

VariableExample

luau

    (
        { any }
    )

luau

    local Events = Warp.fromClientArray({
        "Remote1",
        "Remote2",
        "Remote3",
    })

    -- Usage
    Events.Remote1:Connect(function(...) end)
    Events.Remote2:Connect(function(...) end)
    Events.Remote3:Connect(function(...) end)

## `:Connect`

Connect event to receive incoming from server way.

VariableExample

luau

    (
        callback: (...any) -> ()
    )

luau

    Remote:Connect(function(...)
        print(...)
    end)

## `:Once`

This function likely `:Connect` but it disconnect the event once it fired.

VariableExample

luau

    (
        callback: (...any) -> ()
    )

luau

    Remote:Once(function(...)
        print(...)
    end)

## `:Disconnect`

Disconnect the event connection.

VariableExample

luau

    (
        key: string
    ): boolean

luau

    local connection = Remote:Connect(function(player, ...) end) -- store the key

    Remote:Disconnect(connection)

## `:DisconnectAll`

Disconnect All the event connection.

luau

    Remote:DisconnectAll()

## `:Fire`

Fire the event to the spesific server with data.

VariableExample

luau

    (
        reliable: boolean,
        ...: any
    )

luau

    Remote:Fire(true, "Hello World!")

WARNING

This function have rate limiting it self and configured from server.

## `:Invoke` yield

Semiliar to `:InvokeServer`, but it have timeout system that not exists on `RemoteFunction.InvokeServer`.

VariableExample

luau

    (
        timeout: number,
        ...: any
    ) -> (...any)

luau

    local Request = Remote:Invoke(2, "Hello World!") -- this yield until it response

WARNING

This function is yielded, once it timeout it will return nil.

## `:Wait` yield

Wait the event being triggered.

lua

    Remote:Wait() -- :Wait return number value

WARNING

This function is yielded, Invoke might also ping this one and also causing error.

## `:Destroy`

Disconnect all connection of event and remove the event from Warp list

lua

    Remote:Destroy()


# RbxUtil

| Module | Dependency | Description |
| -- | -- | -- |
| [BufferUtil](https://sleitnick.github.io/RbxUtil/api/BufferUtil) | `BufferUtil = "sleitnick/buffer-util@0.3.2"` | Buffer utilities |
| [Comm](https://sleitnick.github.io/RbxUtil/api/Comm) | `Comm = "sleitnick/comm@1.0.1"` | Comm library for remote communication |
| [Component](https://sleitnick.github.io/RbxUtil/api/Component) | `Component = "sleitnick/component@2.4.8"` | Component class |
| [Concur](https://sleitnick.github.io/RbxUtil/api/Concur) | `Concur = "sleitnick/concur@0.1.2"` | Concurrent task handler |
| [EnumList](https://sleitnick.github.io/RbxUtil/api/EnumList) | `EnumList = "sleitnick/enum-list@2.1.0"` | Enum List class |
| [Find](https://sleitnick.github.io/RbxUtil/api/Find) | `Find = "sleitnick/find@1.0.0"` | Utility function for finding an in the data model hierarchy |
| [Input](https://sleitnick.github.io/RbxUtil/api/Input) | `Input = "sleitnick/input@3.0.0"` | Basic input classes |
| [Loader](https://sleitnick.github.io/RbxUtil/api/Loader) | `Loader = "sleitnick/loader@2.0.0"` | Requires all modules within a given instance |
| [Log](https://sleitnick.github.io/RbxUtil/api/Log) | `Log = "sleitnick/log@0.1.2"` | Log class for logging to PlayFab |
| [Net](https://sleitnick.github.io/RbxUtil/api/Net) | `Net = "sleitnick/net@0.2.0"` | Static networking module |
| [Option](https://sleitnick.github.io/RbxUtil/api/Option) | `Option = "sleitnick/option@1.0.5"` | Represent optional values in Lua |
| [PID](https://sleitnick.github.io/RbxUtil/api/PID) | `PID = "sleitnick/pid@2.1.0"` | PID Controller class |
| [Quaternion](https://sleitnick.github.io/RbxUtil/api/Quaternion) | `Quaternion = "sleitnick/quaternion@0.2.3"` | Quaternion class |
| [Query](https://sleitnick.github.io/RbxUtil/api/Query) | `Query = "sleitnick/query@0.2.0"` | Query instances |
| [Sequent](https://sleitnick.github.io/RbxUtil/api/Sequent) | `Sequent = "sleitnick/sequent@0.1.0"` | Sequent class |
| [Ser](https://sleitnick.github.io/RbxUtil/api/Ser) | `Ser = "sleitnick/ser@1.0.5"` | Ser class for serialization and deserialization |
| [Shake](https://sleitnick.github.io/RbxUtil/api/Shake) | `Shake = "sleitnick/shake@1.1.0"` | Shake class for making things shake |
| [Signal](https://sleitnick.github.io/RbxUtil/api/Signal) | `Signal = "sleitnick/signal@2.0.3"` | Signal class |
| [Silo](https://sleitnick.github.io/RbxUtil/api/Silo) | `Silo = "sleitnick/silo@0.2.0"` | State container class |
| [Spring](https://sleitnick.github.io/RbxUtil/api/Spring) | `Spring = "sleitnick/spring@1.0.0"` | Critically damped spring |
| [Stream](https://sleitnick.github.io/RbxUtil/api/Stream) | `Stream = "sleitnick/stream@0.1.1"` | Stream abstraction wrapper around buffers |
| [Streamable](https://sleitnick.github.io/RbxUtil/api/Streamable) | `Streamable = "sleitnick/streamable@1.2.4"` | Streamable class and StreamableUtil |
| [Symbol](https://sleitnick.github.io/RbxUtil/api/Symbol) | `Symbol = "sleitnick/symbol@2.0.1"` | Symbol |
| [TableUtil](https://sleitnick.github.io/RbxUtil/api/TableUtil) | `TableUtil = "sleitnick/table-util@1.2.1"` | Table utility functions |
| [TaskQueue](https://sleitnick.github.io/RbxUtil/api/TaskQueue) | `TaskQueue = "sleitnick/task-queue@1.0.0"` | Batches tasks that occur on the same execution step |
| [Timer](https://sleitnick.github.io/RbxUtil/api/Timer) | `Timer = "sleitnick/timer@2.0.0"` | Timer class |
| [Tree](https://sleitnick.github.io/RbxUtil/api/Tree) | `Tree = "sleitnick/tree@1.1.0"` | Utility functions for accessing instances in the game hierarchy |
| [Trove](https://sleitnick.github.io/RbxUtil/api/Trove) | `Trove = "sleitnick/trove@1.8.0"` | Trove class for tracking and cleaning up objects |
| [TypedRemote](https://sleitnick.github.io/RbxUtil/api/TypedRemote) | `TypedRemote = "sleitnick/typed-remote@0.3.0"` | Simple networking package for typed RemoteEvents and RemoteFunctions |
| [WaitFor](https://sleitnick.github.io/RbxUtil/api/WaitFor) | `WaitFor = "sleitnick/wait-for@1.0.0"` | WaitFor class for awaiting instances |


[](https://github.com/Sleitnick/RbxUtil/actions/workflows/ci.yaml) [](https://github.com/Sleitnick/RbxUtil/actions/workflows/docs.yaml)

Module| Dependency| Description
---|---|---
[BufferUtil](https://sleitnick.github.io/RbxUtil/api/BufferUtil)| `BufferUtil = "sleitnick/buffer-util@0.3.2"`| Buffer utilities
[Comm](https://sleitnick.github.io/RbxUtil/api/Comm)| `Comm = "sleitnick/comm@1.0.1"`| Comm library for remote communication
[Component](https://sleitnick.github.io/RbxUtil/api/Component)| `Component = "sleitnick/component@2.4.8"`| Component class
[Concur](https://sleitnick.github.io/RbxUtil/api/Concur)| `Concur = "sleitnick/concur@0.1.2"`| Concurrent task handler
[EnumList](https://sleitnick.github.io/RbxUtil/api/EnumList)| `EnumList = "sleitnick/enum-list@2.1.0"`| Enum List class
[Find](https://sleitnick.github.io/RbxUtil/api/Find)| `Find = "sleitnick/find@1.0.0"`| Utility function for finding an in the data model hierarchy
[Input](https://sleitnick.github.io/RbxUtil/api/Input)| `Input = "sleitnick/input@3.0.0"`| Basic input classes
[Loader](https://sleitnick.github.io/RbxUtil/api/Loader)| `Loader = "sleitnick/loader@2.0.0"`| Requires all modules within a given instance
[Log](https://sleitnick.github.io/RbxUtil/api/Log)| `Log = "sleitnick/log@0.1.2"`| Log class for logging to PlayFab
[Net](https://sleitnick.github.io/RbxUtil/api/Net)| `Net = "sleitnick/net@0.2.0"`| Static networking module
[Option](https://sleitnick.github.io/RbxUtil/api/Option)| `Option = "sleitnick/option@1.0.5"`| Represent optional values in Lua
[PID](https://sleitnick.github.io/RbxUtil/api/PID)| `PID = "sleitnick/pid@2.1.0"`| PID Controller class
[Quaternion](https://sleitnick.github.io/RbxUtil/api/Quaternion)| `Quaternion = "sleitnick/quaternion@0.2.3"`| Quaternion class
[Query](https://sleitnick.github.io/RbxUtil/api/Query)| `Query = "sleitnick/query@0.2.0"`| Query instances
[Sequent](https://sleitnick.github.io/RbxUtil/api/Sequent)| `Sequent = "sleitnick/sequent@0.1.0"`| Sequent class
[Ser](https://sleitnick.github.io/RbxUtil/api/Ser)| `Ser = "sleitnick/ser@1.0.5"`| Ser class for serialization and deserialization
[Shake](https://sleitnick.github.io/RbxUtil/api/Shake)| `Shake = "sleitnick/shake@1.1.0"`| Shake class for making things shake
[Signal](https://sleitnick.github.io/RbxUtil/api/Signal)| `Signal = "sleitnick/signal@2.0.3"`| Signal class
[Silo](https://sleitnick.github.io/RbxUtil/api/Silo)| `Silo = "sleitnick/silo@0.2.0"`| State container class
[Spring](https://sleitnick.github.io/RbxUtil/api/Spring)| `Spring = "sleitnick/spring@1.0.0"`| Critically damped spring
[Stream](https://sleitnick.github.io/RbxUtil/api/Stream)| `Stream = "sleitnick/stream@0.1.1"`| Stream abstraction wrapper around buffers
[Streamable](https://sleitnick.github.io/RbxUtil/api/Streamable)| `Streamable = "sleitnick/streamable@1.2.4"`| Streamable class and StreamableUtil
[Symbol](https://sleitnick.github.io/RbxUtil/api/Symbol)| `Symbol = "sleitnick/symbol@2.0.1"`| Symbol
[TableUtil](https://sleitnick.github.io/RbxUtil/api/TableUtil)| `TableUtil = "sleitnick/table-util@1.2.1"`| Table utility functions
[TaskQueue](https://sleitnick.github.io/RbxUtil/api/TaskQueue)| `TaskQueue = "sleitnick/task-queue@1.0.0"`| Batches tasks that occur on the same execution step
[Timer](https://sleitnick.github.io/RbxUtil/api/Timer)| `Timer = "sleitnick/timer@2.0.0"`| Timer class
[Tree](https://sleitnick.github.io/RbxUtil/api/Tree)| `Tree = "sleitnick/tree@1.1.0"`| Utility functions for accessing instances in the game hierarchy
[Trove](https://sleitnick.github.io/RbxUtil/api/Trove)| `Trove = "sleitnick/trove@1.8.0"`| Trove class for tracking and cleaning up objects
[TypedRemote](https://sleitnick.github.io/RbxUtil/api/TypedRemote)| `TypedRemote = "sleitnick/typed-remote@0.3.0"`| Simple networking package for typed RemoteEvents and RemoteFunctions
[WaitFor](https://sleitnick.github.io/RbxUtil/api/WaitFor)| `WaitFor = "sleitnick/wait-for@1.0.0"`| WaitFor class for awaiting instances


Show raw api

        "functions": [],
        "properties": [],
        "types": [],
        "name": "Find",
        "desc": "A utility function for finding objects in the data model hierarchy.\n\nSimilar to `FindFirstChild`, except it explicitly errors if any object\nis not found, as well as a more helpful message as to what wasn't found.\n\n```lua\nlocal find = require(ReplicatedStorage.Packages.find)\n\n-- Find instance \"workspace.Some.Folder.Here.Item\":\nlocal item = find(workspace, \"Some\", \"Folder\", \"Here\", \"Item\")\n```\n\nIn the above example, if \"Folder\" didn't exist, the function would throw an error with the message: `failed to find instance \"Folder\" within \"Workspace.Some\"`.\n\nThe return type is simply `Instance`. Any type-checking should be done on the return value:\n```lua\nlocal part = find(workspace, \"SomePart\") :: BasePart -- Blindly assume and type this as a BasePart\nassert(part:IsA(\"BasePart\")) -- Extra optional precaution to ensure type\n```",
        "source": {
            "line": 26,
            "path": "modules/find/init.luau"


Show raw api

        "functions": [],
        "properties": [],
        "types": [],
        "name": "Symbol",
        "desc": "Represents a unique object.\n\nSymbols are often used as unique keys in tables. This is useful to avoid possible collisions\nwith a key in a table, since the symbol will always be unique and cannot be reconstructed.\n\n\n:::note All Unique\nEvery creation of a symbol is unique, even if the\ngiven names are the same.\n:::\n\n```lua\nlocal Symbol = require(packages.Symbol)\n\n-- Create a symbol:\nlocal symbol = Symbol(\"MySymbol\")\n\n-- The name is optional:\nlocal anotherSymbol = Symbol()\n\n-- Comparison:\nprint(symbol == symbol) --> true\n\n-- All symbol constructions are unique, regardless of the name:\nprint(Symbol(\"Hello\") == Symbol(\"Hello\")) --> false\n\n-- Commonly used as unique keys in a table:\nlocal DATA_KEY = Symbol(\"Data\")\nlocal t = {\n\t-- Can only be accessed using the DATA_KEY symbol:\n\t[DATA_KEY] = {}\n}\n\nprint(t[DATA_KEY]) --> {}\n```",
        "source": {
            "line": 44,
            "path": "modules/symbol/init.luau"


Show raw api

        "functions": [],
        "properties": [],
        "types": [],
        "name": "Input",
        "desc": "The Input package provides access to various user input classes.\n\n- [PreferredInput](/api/PreferredInput)\n- [Mouse](/api/Mouse)\n- [Keyboard](/api/Keyboard)\n- [Touch](/api/Touch)\n- [Gamepad](/api/Gamepad)\n\nReference the desired input modules via the Input package to get started:\n\n```lua\nlocal PreferredInput = require(Packages.Input).PreferredInput\nlocal Mouse = require(Packages.Input).Mouse\nlocal Keyboard = require(Packages.Input).Keyboard\nlocal Touch = require(Packages.Input).Touch\nlocal Gamepad = require(Packages.Input).Gamepad\n```",
        "source": {
            "line": 26,
            "path": "modules/input/init.luau"


View Docs

**Cmdr** is a fully extensible and type safe command console for Roblox developers.

- Great for admin commands, but does much more.
- Make commands that tie in specifically with your game systems.
- Intelligent autocompletion and instant validation.
- Run commands programmatically on behalf of the local user.
- Bind commands to user input.
- Secure: the client and server both validate input separately.
- Embedded commands: dynamically use the output of an inner command when running a command.


## Integrates with your systems

Make commands that integrate and control your existing systems. Use commands to help debug your game during development by triggering events in your game or print out targeted debug information.

## Type-Safe with Intelligent Auto-completion

Discover commands and possible values for arguments naturally with game-state-aware auto-complete. Argument types are validated on the client and server, so in your command code you never have to worry about an argument being of the wrong type or missing.

## 100% Extensible

Cmdr ships with a set of optional default commands for the very most commonly used commands for debugging your game, but the real power of Cmdr is its extensibility. You can register your own commands and argument types so Cmdr can be exactly what you need it to be.

Cmdr is designed specifically so that you can write your own commands and argument types, so that it can fit right in with the rest of your game. In addition to the standard admin commands (teleport, kill, kick), Cmdr is also great for debug commands in your game (say, if you wanted to have a command to give you a weapon, reset a round, teleport you between places in your universe).

Cmdr provides a friendly API that lets the game developer choose if they want to register the default admin commands, register their own commands, choose a different key bind for activating the console, and disabling Cmdr altogether.

Cmdr has a robust and friendly type validation system (making sure strings are strings, players are players, etc), which can give end users real time command validation as they type, and automatic error messages. By the time the command actually gets to your code, you can be assured that all of the arguments are present and of the correct type.

If you have any questions, suggestions, or ideas for Cmdr, or you run into a bug, please don't hesitate to [open an issue](https://github.com/evaera/Cmdr/issues)! PRs are welcome as well.

MIT licensed | Copyright © 2018-present eryn L. K.


# CmdrClient client only

↪ Extends [Cmdr](https://eryn.io/Cmdr/api/Cmdr.html)

## Properties

↪ Inherited from [Cmdr](https://eryn.io/Cmdr/api/Cmdr.html)

### # `Registry`

`CmdrClient.Registry: `````[Registry](https://eryn.io/Cmdr/api/Registry.html#registry)``````

Refers to the current command Registry.

↪ Inherited from [Cmdr](https://eryn.io/Cmdr/api/Cmdr.html)

### # `Dispatcher`

`CmdrClient.Dispatcher: `````[Dispatcher](https://eryn.io/Cmdr/api/Dispatcher.html#dispatcher)``````

Refers to the current command Dispatcher.

↪ Inherited from [Cmdr](https://eryn.io/Cmdr/api/Cmdr.html)

### # `Util`

`CmdrClient.Util: `````[Util](https://eryn.io/Cmdr/api/Util.html#util)``````

Refers to a table containing many useful utility functions.

### # `Enabled`

`CmdrClient.Enabled: `````boolean``````

### # `PlaceName`

`CmdrClient.PlaceName: `````string``````

### # `ActivationKeys`

`CmdrClient.ActivationKeys: `````dictionary<Enum.KeyCode, true>``````

## Instance Methods

### # `SetActivationKeys`

`CmdrClient.``SetActivationKeys(keys: ``array<Enum.KeyCode>``) → ```

Sets the key codes that will hide or show Cmdr.

#### Parameters

Name | Type | Required |
---|---|---|---
`keys` | ```array<Enum.KeyCode>``` |  ✔  |

#### Returns

Type |

### # `SetPlaceName`

`CmdrClient.``SetPlaceName(labelText: ``string``) → ```

Sets the place name label that appears when executing commands. This is useful for a quick way to tell what game you're playing in a universe game.

#### Parameters

Name | Type | Required |
---|---|---|---
`labelText` | ```string``` |  ✔  |

#### Returns

Type |

### # `SetEnabled`

`CmdrClient.``SetEnabled(isEnabled: ``boolean``) → ```

Sets whether or not Cmdr can be shown via the defined activation keys. Useful for when you want users to need to opt-in to show the console in a settings menu.

#### Parameters

Name | Type | Required |
---|---|---|---
`isEnabled` | ```boolean``` |  ✔  |

#### Returns

Type |

### # `Show`

`CmdrClient.``Show() → ```

Shows the Cmdr window explicitly. Does not do anything if Cmdr is not enabled.

#### Returns

Type |

### # `Hide`

`CmdrClient.``Hide() → ```

Hides the Cmdr window.

#### Returns

Type |

### # `Toggle`

`CmdrClient.``Toggle() → ```

Toggles visibility of the Cmdr window. Will not show if Cmdr is not enabled.

#### Returns

Type |

### # `HandleEvent`

`CmdrClient.``HandleEvent(

event: ``string``,
handler: ``function(...?: ``any?``) → ``

) → ```

#### Parameters

Name | Type | Required |
---|---|---|---
`event` | ```string``` |  ✔  |
`handler` |  ```function(...?: ``any?``) → ``` Details #### Parameters | Name | Type | Required |
---|---|---|---
`...` | ```any?``` |  ✘  |

#### Returns

Type |

✔  |

#### Returns

Type |

### # `SetMashToEnable`

`CmdrClient.``SetMashToEnable(isEnabled: ``boolean``) → ```

#### Parameters

Name | Type | Required |
---|---|---|---
`isEnabled` | ```boolean``` |  ✔  |

#### Returns

Type |

### # `SetActivationUnlocksMouse`

`CmdrClient.``SetActivationUnlocksMouse(isEnabled: ``boolean``) → ```

#### Parameters

Name | Type | Required |
---|---|---|---
`isEnabled` | ```boolean``` |  ✔  |

#### Returns

Type |

v1.6.0+

### # `SetHideOnLostFocus`

`CmdrClient.``SetHideOnLostFocus(isEnabled: ``boolean``) → ```

#### Parameters

Name | Type | Required |
---|---|---|---
`isEnabled` | ```boolean``` |  ✔  |

#### Returns

Type |

← [ Cmdr ](https://eryn.io/Cmdr/api/Cmdr.html) [ CommandContext ](https://eryn.io/Cmdr/api/CommandContext.html) →
  *[Registry]: The registry handles registering commands, types, and hooks.
  *[Dispatcher]: The Dispatcher handles parsing, validating, and evaluating commands.


# # Set-up

### # Installation

Pick one of the below methods to install Cmdr:

#### # Manual

You can download the latest model file release from the [releases section](https://github.com/evaera/Cmdr/releases/latest), but this may not always be the most up to date version of Cmdr. You'll want to put this is a server directory, like ServerScriptService.

#### # Advanced

Cmdr has no dependencies, so it can also be easily included as a Git submodule and synced in with the rest of your project with [Rojo](https://github.com/LPGhatguy/rojo). If you don't know how to do this already, then please see method 1 😃

### # Warning

DO NOT MODIFY SOURCE CODE TO CHANGE BEHAVIOR

Please **do not** modify the source code of Cmdr for your game. Instead, use its API to customize the behavior you want. Modifying the source code makes it much harder for you to receive feature updates.

There should be **no reason** to modify the source code of Cmdr (unless you are adding a brand new feature or fixing a bug).

### # Server setup (required)

You should create a folder to keep your commands inside, and then register them on the server. However, you only need to register commands and types on the server. There should be no need to modify the actual Cmdr library itself.

    -- This is a script you would create in ServerScriptService, for example.
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Cmdr = require(path.to.Cmdr)

    Cmdr:RegisterDefaultCommands() -- This loads the default set of commands that Cmdr comes with. (Optional)
    -- Cmdr:RegisterCommandsIn(script.Parent.CmdrCommands) -- Register commands from your own folder. (Optional)

1
2
3
4
5
6

The Cmdr GUI will be inserted into StarterGui if it doesn't already exist. You can customize the GUI to your liking (changing colors, etc.) if you play the game, copy the GUI, stop the game, and then paste it in to StarterGui. Of course, this is completely optional.

CLIENT SETUP ALSO REQUIRED

You need to require Cmdr on the server _and_ on the client for it to be fully loaded. Keep going! ↓

### # Client setup (required)

From the client, you also need to require the CmdrClient module.

After the server code above runs, CmdrClient will be inserted into ReplicatedStorage automatically.

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local Cmdr = require(ReplicatedStorage:WaitForChild("CmdrClient"))

    -- Configurable, and you can choose multiple keys
    Cmdr:SetActivationKeys({ Enum.KeyCode.F2 })
    -- See below for the full API.

1
2
3
4
5
6

[ Commands ](https://eryn.io/Cmdr/guide/Commands.html) →


# # Hooks

Hooks are callback functions that you can register which _hook_ into the command execution process. Hooks are extremely useful: they can be used for implementing a custom permission system, logging commands, or overriding command output.

Hooks can be registered on both the server and the client. Server commands will run server and client hooks, and client commands will run only client hooks. Depending on your application, you may need to register hooks on one or both. For example, logging may only need to be registered on the server, but permissions might need to be registered on the client in addition to the server.

There can be many hooks of each type, and they are all run until one returns a string, which will replace the command response in the console.

## # BeforeRun

The callback is passed the CommandContext for the relevant command. The hooks are the last thing to run before the command itself, so all properties are available.

This hook can be used to interrupt command execution (useful for permissions) by returning a string. The returned string will replace the command output on the executing user's screen. If the callback returns nothing (`nil`), then the command will run normally.

Security Warning

Commands will be blocked from running in-game unless you configure at least one BeforeRun hook.

As a quick way to register hooks on both the server and the client, you can make a folder for your hooks, with module scripts in them which return a function. Similar to Types, if you call `Cmdr:RegisterHooksIn(yourFolderHere)` from the server, Cmdr will load all ModuleScripts in the folder on the server and the client, so you only need to write your code once.

    -- A ModuleScript inside your hooks folder.
    return function (registry)
        registry:RegisterHook("BeforeRun", function(context)
            if context.Group == "DefaultAdmin" and context.Executor.UserId ~= game.CreatorId then
                return "You don't have permission to run this command"
            end
        end)
    end

1
2
3
4
5
6
7
8

## # AfterRun

The AfterRun hook runs, as its name implies, directly after a command is run. The callback is also passed a CommandContext, but the `Response` property is now available, which is the response from the command implementation (what would normally be displayed after running the command).

If this callback returns a string, then it will replace the normal response on the user's screen. If the callback returns nothing (`nil`), then the response will be shown normally.

This hook is most useful for logging. Since we don't want to add this hook on the client in this example, we can just require the server version of Cmdr and add this hook directly right here (as opposed to what we did in the BeforeRun example, which adds the hook to the client as well):

    Cmdr.Registry:RegisterHook("AfterRun", function(context)
      print(context.Response) -- see the actual response from the command execution
      return "Returning a string from this hook replaces the response message with this text"
    end)

1
2
3
4

← [ Types ](https://eryn.io/Cmdr/guide/Types.html) [ Network Event Handlers ](https://eryn.io/Cmdr/guide/NetworkEventHandlers.html) →


# ArgumentContext

## Properties

### # `Command`

`ArgumentContext.Command: `````[CommandContext](https://eryn.io/Cmdr/api/CommandContext.html#commandcontext)``````

The command that this argument belongs to.

### # `Name`

`ArgumentContext.Name: `````string``````

The name of this argument.

### # `Type`

`ArgumentContext.Type: `````[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)``````

The type definition for this argument.

### # `Required`

`ArgumentContext.Required: `````boolean``````

Whether or not this argument was required.

### # `Executor`

`ArgumentContext.Executor: `````Player``````

The player that ran the command this argument belongs to.

### # `RawValue`

`ArgumentContext.RawValue: `````string``````

The raw, unparsed value for this argument.

### # `RawSegments`

`ArgumentContext.RawSegments: `````array<string>``````

An array of strings representing the values in a comma-separated list, if applicable.

### # `Prefix`

`ArgumentContext.Prefix: `````string``````

The prefix used in this argument (like `%` in `%Team`). Empty string if no prefix was used. See Prefixed Union Types for more details.

## Instance Methods

### # `GetValue`

`ArgumentContext.``GetValue() → ``any`````

Returns the parsed value for this argument.

#### Returns

Type |
```any``` |

### # `GetTransformedValue`

`ArgumentContext.``GetTransformedValue(segment: ``number``) → ``any...`````

Returns the _transformed_ value from this argument, see Types.

#### Parameters

Name | Type | Required |
---|---|---|---
`segment` | ```number``` |  ✔  |

#### Returns

Type |
```any...``` |

← [ Meta-Commands ](https://eryn.io/Cmdr/guide/MetaCommands.html) [ Cmdr ](https://eryn.io/Cmdr/api/Cmdr.html) →


# Cmdr server only

## Properties

### # `Registry`

`Cmdr.Registry: `````[Registry](https://eryn.io/Cmdr/api/Registry.html#registry)``````

Refers to the current command Registry.

### # `Dispatcher`

`Cmdr.Dispatcher: `````[Dispatcher](https://eryn.io/Cmdr/api/Dispatcher.html#dispatcher)``````

Refers to the current command Dispatcher.

### # `Util`

`Cmdr.Util: `````[Util](https://eryn.io/Cmdr/api/Util.html#util)``````

Refers to a table containing many useful utility functions.

← [ ArgumentContext ](https://eryn.io/Cmdr/api/ArgumentContext.html) [ CmdrClient ](https://eryn.io/Cmdr/api/CmdrClient.html) →
  *[Registry]: The registry handles registering commands, types, and hooks.
  *[Dispatcher]: The Dispatcher handles parsing, validating, and evaluating commands.


# # Types

By default, these types are available:

Type name | Data type | Type name | Data type
---|---|---|---
`string` | `string` | `strings` | `array<string>`
`number` | `number` | `numbers` | `array<number>`
`integer` | `number` | `integers` | `array<number>`
`boolean` | `boolean` | `booleans` | `array<boolean>`
`player` | `Player` | `players` | `array<Player>`
`playerId` | `number` | `playerIds` | `array<number>`
`team` | `Team` | `teams` | `array<Team>`
|  | `teamPlayers` | `array<Player>`
`command` | `string` | `commands` | `array<string>`
`userInput` | `Enum.UserInputType \| Enum.KeyCode` | `userInputs` | `array<Enum.UserInputType \| Enum.KeyCode>`
`brickColor` | `BrickColor` | `brickColors` | `array<BrickColor>`
`teamColor` | `BrickColor` | `teamColors` | `array<BrickColor>`
`color3` | `Color3` | `color3s` | `array<Color3>`
`hexColor3` | `Color3` | `hexColor3s` | `array<Color3>`
`brickColor3` | `Color3` | `brickColor3s` | `array<Color3>`
`vector3` | `Vector3` | `vector3s` | `array<Vector3>`
`vector2` | `Vector2` | `vector2s` | `array<Vector2>`
`duration` | `number` | `durations` | `array<number>`
`storedKey` | `string` | `storedKeys` | `array<strings>`
`url` | `string` | `urls` | `array<strings>`

Plural types (types that return a table) are listable, so you can provide a comma-separated list of values.

Custom types are defined as tables that implement specific named functions. When Types are in a ModuleScript, the ModuleScript should not return the table directly; instead it should return a function, which accepts the Registry as a parameter. You should then call `registry:RegisterType("typeName", yourTable)` to register it.

Check out the [API reference](https://eryn.io/Cmdr/api/Registry.html#typedefinition) for a full reference of all available options.

    local intType = {
        Transform = function (text)
            return tonumber(text)
        end;

        Validate = function (value)
            return value ~= nil and value == math.floor(value), "Only whole numbers are valid."
        end;

        Parse = function (value)
            return value
        end

    return function (registry)
        registry:RegisterType("integer", intType)
    end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Take a gander at the [built-in types](https://github.com/evaera/Cmdr/tree/master/Cmdr/BuiltInTypes) for more examples.

## # Default value

You can specify a "default value" for your type by adding a `Default` function to it. For example, the default value for the `players` type is the name of the player who ran the command. The `Default` function should always return a **string**, as this is inserted BEFORE parsing.

For any argument that is type with a default value, you can simply type a `.` in Cmdr and the default value will automatically be used in its place.

## # Enum types

Because Enum types are so common, there is a special function that easily lets you create an Enum type. When a command has an argument of this type, it'll always be a string matching exactly one of the strings in the array you define (see below).

    return function (registry)
        registry:RegisterType("place", registry.Cmdr.Util.MakeEnumType("Place", {"World 1", "World 2", "World 3", "Final World"}))
    end

1
2
3

← [ Commands ](https://eryn.io/Cmdr/guide/Commands.html) [ Hooks ](https://eryn.io/Cmdr/guide/Hooks.html) →


# CommandContext

## Properties

### # `Cmdr`

`CommandContext.Cmdr: `````[Cmdr](https://eryn.io/Cmdr/api/Cmdr.html#cmdr) | [CmdrClient](https://eryn.io/Cmdr/api/CmdrClient.html#cmdrclient)``````

A reference to Cmdr. This may either be the server or client version of Cmdr depending on where the command is running.

### # `Dispatcher`

`CommandContext.Dispatcher: `````[Dispatcher](https://eryn.io/Cmdr/api/Dispatcher.html#dispatcher)``````

The dispatcher that created this command.

### # `Name`

`CommandContext.Name: `````string``````

The name of the command.

### # `Alias`

`CommandContext.Alias: `````string``````

The specific alias of this command that was used to trigger this command (may be the same as `Name`)

### # `RawText`

`CommandContext.RawText: `````string``````

The raw text that was used to trigger this command.

### # `Group`

`CommandContext.Group: ```````````

The group this command is a part of. Defined in command definitions, typically a string.

### # `State`

`CommandContext.State: `````table``````

A blank table that can be used to store user-defined information about this command's current execution. This could potentially be used with hooks to add information to this table which your command or other hooks could consume.

### # `Aliases`

`CommandContext.Aliases: `````array<string>``````

Any aliases that can be used to also trigger this command in addition to its name.

### # `Description`

`CommandContext.Description: `````string``````

The description for this command from the command definition.

### # `Executor`

`CommandContext.Executor: `````Player``````

The player who ran this command.

### # `RawArguments`

`CommandContext.RawArguments: `````array<string>``````

An array of strings which is the raw value for each argument.

### # `Arguments`

`CommandContext.Arguments: `````array<[ArgumentContext](https://eryn.io/Cmdr/api/ArgumentContext.html#argumentcontext)>``````

An array of ArgumentContext objects, the parsed equivalent to RawArguments.

### # `Response`

`CommandContext.Response: `````string?``````

The command output, if the command has already been run. Typically only accessible in the AfterRun hook.

## Instance Methods

### # `GetArgument`

`CommandContext.``GetArgument(index: ``number``) → ``[ArgumentContext](https://eryn.io/Cmdr/api/ArgumentContext.html#argumentcontext)`````

Returns the ArgumentContext for the given index.

#### Parameters

Name | Type | Required |
---|---|---|---
`index` | ```number``` |  ✔  |

#### Returns

Type |
```[ArgumentContext](https://eryn.io/Cmdr/api/ArgumentContext.html#argumentcontext)``` |

### # `GetData`

`CommandContext.``GetData() → ```

Returns the command data that was sent along with the command. This is the return value of the Data function from the command definition.

#### Returns

Type |

### # `GetStore`

`CommandContext.``GetStore(name: ``string``) → ``table`````

Returns a table of the given name. Always returns the same table on subsequent calls. Useful for storing things like ban information. Same as [Registry.GetStore](https://eryn.io/Cmdr/api/Registry.html#getstore).

#### Parameters

Name | Type | Required |
---|---|---|---
`name` | ```string``` |  ✔  |

#### Returns

Type |
```table``` |

### # `SendEvent`

`CommandContext.``SendEvent(

player: ``Player``,
event: ``string``

) → ```

Sends a network event of the given name to the given player. See Network Event Handlers.

#### Parameters

Name | Type | Required |
---|---|---|---
`player` | ```Player``` |  ✔  |
`event` | ```string``` |  ✔  |

#### Returns

Type |

### # `BroadcastEvent`

`CommandContext.``BroadcastEvent(

event: ``string``,
...: ``any``

) → ```

Broadcasts a network event to all players. See Network Event Handlers.

#### Parameters

Name | Type | Required |
---|---|---|---
`event` | ```string``` |  ✔  |
`...` | ```any``` |  ✔  |

#### Returns

Type |

### # `Reply`

`CommandContext.``Reply(

text: ``string``,
color?: ``Color3?``

) → ```

Prints the given text in the user's console. Useful for when a command needs to print more than one message or is long-running. You should still `return` a string from the command implementation when you are finished, `Reply` should only be used to send additional messages before the final message.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`color` | ```Color3?``` |  ✘  |

#### Returns

Type |

v1.6.0+

### # `HasImplementation`

`CommandContext.``HasImplementation() → ``boolean`````

Returns `true` if the command has an implementation on this machine. For example, this function will return `false` from the client if you call it on a command that only has a server-side implementation. Note that commands can potentially run on both the client and the server, so what this property returns on the server is not related to what it returns on the client, and vice versa. Likewise, receiving a return value of `true` on the client does not mean that the command won't run on the server, because Cmdr commands can run a first part on the client and a second part on the server. This function only answers one question if you run the command; does it run any code as a result of that on this machine?

#### Returns

Type |
```boolean``` |

← [ CmdrClient ](https://eryn.io/Cmdr/api/CmdrClient.html) [ Dispatcher ](https://eryn.io/Cmdr/api/Dispatcher.html) →
  *[Dispatcher]: The Dispatcher handles parsing, validating, and evaluating commands.


# Util

## Types

### # `NamedObject`

`interface ``NamedObject {``

Name: `````string`````

Any object with a `Name` property.

## Static Functions

### # `MakeDictionary` static

`Util.``MakeDictionary(array: ``array<T>``) → ``dictionary<T, true>`````

Accepts an array and flips it into a dictionary, its values becoming keys in the dictionary with the value of `true`.

#### Parameters

Name | Type | Required |
---|---|---|---
`array` | ```array<T>``` |  ✔  |

#### Returns

Type |
```dictionary<T, true>``` |

### # `Map` static

`Util.``Map(

array: ``array<T>``,
mapper: ``function(

value: ``T``,
index: ``number``

) → ``U````

) → ``array<U>`````

Maps values from one array to a new array. Passes each value through the given callback and uses its return value in the same position in the new array.

#### Parameters

Name | Type | Required |
---|---|---|---
`array` | ```array<T>``` |  ✔  |
`mapper` |  ```function(value: ``T``,
index: ``number``) → ``U````` Details #### Parameters | Name | Type | Required |
---|---|---|---
`value` | ```T``` |  ✔  |
`index` | ```number``` |  ✔  |

#### Returns

Type |
```U``` |

✔  |

#### Returns

Type |
```array<U>``` |

### # `Each` static

`Util.``Each(

mapper: ``function(value: ``T``) → ``U````,
...: ``T``

) → ``U...`````

Maps arguments #2-n through callback and returns all values as tuple.

#### Parameters

Name | Type | Required |
---|---|---|---
`mapper` |  ```function(value: ``T``) → ``U````` Details #### Parameters | Name | Type | Required |
---|---|---|---
`value` | ```T``` |  ✔  |

#### Returns

Type |
```U``` |

✔  |
`...` | ```T``` |  ✔  |

#### Returns

Type |
```U...``` |

### # `MakeFuzzyFinder` static

`Util.``MakeFuzzyFinder(set: ``

       array<string>
     | array<Instance>
     | array<EnumItem>
     | array<NamedObject>
     | Instance

``) → ``function(

text: ``string``,
returnFirst?: ``boolean?``

) → ``any```````

Makes a fuzzy finder for the given set or container. You can pass an array of strings, array of instances, array of EnumItems, array of dictionaries with a Name key or an instance (in which case its children will be used).

#### Parameters

Name | Type | Required |
---|---|---|---
`set` |  ### # `` ```

       array<string>
     | array<Instance>
     | array<EnumItem>
     | array<NamedObject>
     | Instance

``` |  ✔  |

#### Returns

Type |
```function(text: ``string``,
returnFirst?: ``boolean?``) → ``any````` Details #### Parameters | Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`returnFirst` | ```boolean?``` |  ✘  |

#### Returns

Type |
```any``` |

Accepts a string and returns a table of matching objects. Exact matches are inserted in the front of the resultant array.

### # `GetNames` static

`Util.``GetNames(instances: ``array<NamedObject>``) → ``array<string>`````

Accepts an array of instances (or anything with a Name property) and maps them into an array of their names.

#### Parameters

Name | Type | Required |
---|---|---|---
`instances` | ```array<NamedObject>``` |  ✔  |

#### Returns

Type |
```array<string>``` |

### # `SplitStringSimple` static

`Util.``SplitStringSimple(

text: ``string``,
separator: ``string``

) → ``array<string>`````

Slits a string into an array split by the given separator.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`separator` | ```string``` |  ✔  |

#### Returns

Type |
```array<string>``` |

### # `SplitString` static

`Util.``SplitString(

text: ``string``,
max?: ``number?``

) → ``array<string>`````

Splits a string by spaces, but taking double-quoted sequences into account which will be treated as a single value.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`max` | ```number?``` |  ✘  |

#### Returns

Type |
```array<string>``` |

### # `TrimString` static

`Util.``TrimString(text: ``string``) → ``string`````

Trims whitespace from both sides of a string.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |

#### Returns

Type |
```string``` |

### # `GetTextSize` static

`Util.``GetTextSize(

text: ``string``,
label: ``TextLabel``,
size?: ``Vector2?``

) → ``Vector2`````

Returns the text bounds size as a Vector2 based on the given label and optional display size. If size is omitted, the absolute width is used.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`label` | ```TextLabel``` |  ✔  |
`size` | ```Vector2?``` |  ✘  |

#### Returns

Type |
```Vector2``` |

### # `MakeEnumType` static

`Util.``MakeEnumType(

type: ``string``,
values: ``array<string | { Name``

) → ``[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)`````

Makes an Enum type out of a name and an array of strings. See Enum Values.

#### Parameters

Name | Type | Required |
---|---|---|---
`type` | ```string``` |  ✔  |
`values` | ```array<string | { Name``` |  ✔  |

#### Returns

Type |
```[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)``` |

### # `MakeListableType` static

`Util.``MakeListableType(

type: ``[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)``,
override?: ``dictionary``

) → ``[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)`````

Takes a singular type and produces a plural (listable) type out of it.

#### Parameters

Name | Type | Required |
---|---|---|---
`type` | ```[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)``` |  ✔  |
`override?` | ```dictionary``` |  ✔  |

#### Returns

Type |
```[TypeDefinition](https://eryn.io/Cmdr/api/Registry.html#typedefinition)``` |

### # `MakeSequenceType` static

`Util.``MakeSequenceType(options: ```{``

TransformEach

ValidateEach

``}` & ```(`{``

Parse

``}` | `{``

Constructor

``}`)`````) → ```

A helper function that makes a type which contains a sequence, like Vector3 or Color3. The delimeter can be either `,` or whitespace, checking `,` first. options is a table that can contain:

  * `TransformEach`: a function that is run on each member of the sequence, transforming it individually.
  * `ValidateEach`: a function is run on each member of the sequence validating it. It is passed the value and the index at which it occurs in the sequence. It should return true if it is valid, or false and a string reason if it is not.

And one of:

  * `Parse`: A function that parses all of the values into a single type.
  * `Constructor`: A function that expects the values unpacked as parameters to create the parsed object. This is a shorthand that allows you to set Constructor directly to Vector3.new, for example.

#### Parameters

Name | Type | Required |
---|---|---|---
`options` |  ### # `` ````{``TransformEach ValidateEach``}` & ```(`{``Parse``}` | `{``Constructor``}`)`````` |  ✔  |

#### Returns

Type |

### # `SplitPrioritizedDelimeter` static

`Util.``SplitPrioritizedDelimeter(

text: ``string``,
delimters: ``array<string>``

) → ``array<string>`````

Splits a string by a single delimeter chosen from the given set. The first matching delimeter from the set becomes the split character.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`delimters` | ```array<string>``` |  ✔  |

#### Returns

Type |
```array<string>``` |

### # `SubstituteArgs` static

`Util.``SubstituteArgs(

text: ``string``,
replace: ``

       array<string>
     | dictionary<string, string>
     | function(var: string) → string

) → ``string`````

Accepts a string with arguments (such as $1, $2, $3, etc) and a table or function to use with string.gsub. Returns a string with arguments replaced with their values.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`replace` |  ### # `` ```

       array<string>
     | dictionary<string, string>
     | function(var: string) → string

``` |  ✔  |

#### Returns

Type |
```string``` |

### # `RunEmbeddedCommands` static

`Util.``RunEmbeddedCommands(

dispatcher: ``[Dispatcher](https://eryn.io/Cmdr/api/Dispatcher.html#dispatcher)``,
commandString: ``string``

) → ``string`````

Accepts the current dispatcher and a command string. Parses embedded commands from within the string, evaluating to the output of the command when run with `dispatcher:EvaluateAndRun`. Returns the response string.

#### Parameters

Name | Type | Required |
---|---|---|---
`dispatcher` | ```[Dispatcher](https://eryn.io/Cmdr/api/Dispatcher.html#dispatcher)``` |  ✔  |
`commandString` | ```string``` |  ✔  |

#### Returns

Type |
```string``` |

### # `EmulateTabstops` static

`Util.``EmulateTabstops(

text: ``string``,
tabWidth: ``number``

) → ``string`````

Returns a string emulating `\t` tab stops with spaces.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |
`tabWidth` | ```number``` |  ✔  |

#### Returns

Type |
```string``` |

### # `ParseEscapeSequences` static

`Util.``ParseEscapeSequences(text: ``string``) → ``string`````

Replaces escape sequences with their fully qualified characters in a string. This only parses `\n`, `\t`, `\uXXXX`, and `\xXX` where `X` is any hexadecimal character.

#### Parameters

Name | Type | Required |
---|---|---|---
`text` | ```string``` |  ✔  |

#### Returns

Type |
```string``` |

← [ Registry ](https://eryn.io/Cmdr/api/Registry.html)
  *[NamedObject]: Any object with a `Name` property.
  *[Dispatcher]: The Dispatcher handles parsing, validating, and evaluating commands.