Forest Logo
search
package_2

tether

By @awakesl

Roblox

Mirrored from Wally

Tether

Real-time state between every server of your game, so they play as one world.

  • Streaming: each server posts and receives about 8 times a second, and every value arrives with its age.
  • Interest: put things under keys (a chunk, a room, a party). A server only gets what's under the keys it wants.
  • Fleet-wide ids: mint ids that never collide across servers.
  • Ownership: send a message to whichever server owns a thing, like damage to whoever owns the target.
  • Contested things: drop items nobody owns. When two servers grab one, exactly one wins.
  • Late joiners: a server that starts watching a key gets the newest state under it.
  • Smooth playback: a playout buffer on the receiving side, with posts aligned to the relay's tick across servers.
  • Small packets: you declare each message's fields (u8 to u32, bit flags, quantised floats), and the relay never reads your payloads.

Tether has no built-in idea of position, damage or players. You declare every kind of message.

Example

local Tether = require(ReplicatedStorage.Packages.Tether)

local net = Tether.connect({
    url = "https://your-relay.example/publish",
    identity = HttpService:GenerateGUID(false),
    key = HttpService:GetSecret("tether"),
    kinds = {
        motion = {
            id = 1,
            routing = "key",          -- to every server watching where it is
            collapsible = true,       -- a newer position replaces an unsent older one
            retention = "replace",    -- late joiners get the newest
            fields = {
                { "x", "u16", scale = 4, offset = -8192 },
                { "z", "u16", scale = 4, offset = -8192 },
            },
        },
    },
})

RunService.Heartbeat:Connect(function(dt)
    net:step(dt)
end)
repeat task.wait() until net:ready()

local id = net:mint()
net:place(id, "12:7")
net:want({ "12:7", "12:8" })
net:send("motion", id, { x = 100.5, z = -250.25 })

net:on("motion", function(subject, values, ageMs)
    -- another server's thing moved
end)

Setup

  1. Add it with Wally:

    Tether = "awakesl/tether@0.2.0"
    
  2. Run the relay where your servers can reach it over HTTPS:

    cd relay
    cargo build --release
    TETHER_KEY=your-secret target/release/tether-relay
    

    To test from Studio, scripts\dev starts it behind a free cloudflared tunnel.

  3. Turn on HTTP requests for the game, and add the key as a Secret named tether.

Docs

docs/Guide.md covers declaring kinds and field types, routing, ownership and claims, the tick, and every relay setting.

Repo

src/       the Luau library
relay/     the relay, in Rust
test/      the specs, as they run in a place
scripts/   the dev launcher and headless rigs
docs/      the guide

MIT licence.

Package Details

Install command (Click to copy)


Version

0.2.0

License

MIT

check_circle

Safe for commercial use

Automated license review — not legal advice.