riptide/core

A strict Luau framework for Roblox with side-specific APIs, typed networking/state, module lifecycle orchestration, and sandboxed plugins.

Riptide Banner

GitHub Repository Documentation GitHub Releases Changelog Pesde Package Wally Package Tests



Riptide was built from the ground up for production Roblox games. It solves the most common architecture problems while remaining invisible, staying out of your way, and scaling elegantly.

๐ŸŒŠ Maelstrom-3 preview

Version 0.9.0-maelstrom.3 is the latest preview release. 0.8.2 remains the latest stable release. Follow the Maelstrom-3 guide to get started.


โœจ Key Features

  • ๐Ÿ“… Deterministic Lifecycle: Phased initialization (Load โ†’ Init โ†’ Start) ensures modules and plugins load in a predictable, race-free order.
  • ๐Ÿ”Œ Framework-Layer Plugins: Sandboxed plugins load before game modules, reach bounded Start readiness before gameplay starts, support dependency ordering, and stay isolated so third-party failures cannot bring down the framework.
  • โšก Independent Signals: Typed events with constant-time disconnect; callbacks run in reusable threads so a yielding or failing listener does not block the others.
  • ๐Ÿ“ก Unified Networking: Multiplexed RemoteEvent and UnreliableRemoteEvent networking with flat, closure-free middleware chains.
  • ๐Ÿ›ก๏ธ Typed Remote Validation: Enforce client payload types at the network boundary via Riptide.Network.RegisterTyped() in server modules and composable Guard validators.
  • ๐Ÿ“ฆ 100% Strict Luau: Written entirely with --!strict, exporting clean API interfaces for full autocomplete and type-checking.
  • ๐Ÿ› ๏ธ Built-in Power: Ships with Sleitnick's Trove resource tracker, EventBus pub/sub, Guard schema validators, StateMachine, Async utilities, and server-authoritative State replication.

๐Ÿ“ฆ Installation

Install the Maelstrom-3 preview with either package manager. For the stable release, use 0.8.2.

Via Pesde (Recommended)

In your game folder, run pesde init and choose roblox and pesde/scripts_rojo. Then run:

pesde add riptide/[email protected] --alias Riptide
pesde install

Result: pesde.toml lists Riptide and the package is in roblox_packages/Riptide.

Via Wally

Run wally init in your game folder. Add this line under [dependencies] in wally.toml:

Riptide = "riptide/[email protected]"

Run wally install. Result: Riptide is in Packages/Riptide.

Manual (.rbxm)

Download Riptide.rbxm from the Maelstrom-3 release and insert it as ReplicatedStorage/Packages/Riptide.


๐Ÿ Quick Look

Riptide organizes your game logic into Services (server) and Controllers (client). Each module follows a clean lifecycle: modules are loaded first, Init runs synchronously, and Start runs asynchronously afterward.

-- ServerScriptService/Services/CoinsService.lua
--!strict
local CoinsService = {}

function CoinsService:Init(Riptide)
    -- Init runs synchronously. Register network handlers and grab
    -- references to other services here โ€” everything is loaded but
    -- not yet started.
    Riptide.Network.RegisterTyped("BuyItem", {
        Riptide.Guard.String(50),       -- itemId:  string, max 50 chars
        Riptide.Guard.Number(0, 1000),  -- price:   number, 0โ€“1000
    }, function(player, itemId, price)
        print(player.Name .. " bought " .. itemId .. " for " .. price .. " coins")
    end)
end

function CoinsService:Start(Riptide)
    -- Start runs in its own coroutine โ€” safe to yield here.
    self.Trove = Riptide.Trove.new()
    print("CoinsService is running!")
end

function CoinsService:OnPlayerAdded(Riptide, player)
    Riptide.State:SetForPlayer(player, "coins", 0)
end

return CoinsService

Launch the server from a server script:

-- ServerScriptService/main.server.lua
local ReplicatedStorage  = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Riptide = require(ReplicatedStorage.Packages.Riptide).Server

Riptide.Launch({
    ModulesFolder = ServerScriptService.Services,
})

Launch the client from a LocalScript:

-- StarterPlayerScripts/main.client.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Riptide = require(ReplicatedStorage.Packages.Riptide).Client

Riptide.Launch({
    ModulesFolder = Players.LocalPlayer.PlayerScripts.Controllers,
})

๐Ÿ“š Documentation

Complete setup guides, API reference, and examples:

๐Ÿ‘‰ Riptide Documentation


๐Ÿ“„ License

MIT โ€” see LICENSE.