Packages & DLC
Three flavours of bundle, one underlying format. Drop-in DLC, third-party
add-ons, and the project itself all ship as encrypted
.managed files; only the layout around them differs.
The .managed format
A .managed file is one of two kinds:
-
<id>.scripts.managed, encrypted JSON of every.luaufile in the package, plus metadata (id, name, version, creator, entry script, file mode). -
<id>.assets.managed, encrypted JSON of every file underassets/, base64-encoded. Withshard-assetson, splits into<id>.assets.shard<N>.managedfiles plus a<id>.assets.manifest.managedindex.
Both are AES-256-GCM encrypted with a key baked into the engine binary. The encryption is intentional but not cryptographic protection, it's there to keep casual asset rippers out, not to defeat a determined extractor.
Loading order
At launcher startup the engine scans Managed/ next to the
executable and loads every .managed file. Each file's
declared id ("id" in ManagedInfo.toml or the
project's exe-name) becomes a require namespace. The
package whose id matches the launcher's
default_id trailer field is the entry, it's what
runs when the launcher boots.
Generated/
MyGame.exe # launcher; default_id = "MyGame"
Managed/
MyGame.scripts.managed # ← entry: id = "MyGame"
MyGame.assets.managed
Physics.scripts.managed # DLC: id = "Physics"
Physics.assets.managed
community-mod.scripts.managed # Workshop drop-in
require() across packages
Every package gets its own require namespace prefixed with
@id/:
-- From inside MyGame:
local phys = require("@Physics/init") -- DLC API
local common = require("@self/lib/util") -- own package, root-relative
local sib = require("./helper") -- caller-relative
@self is an alias for the calling script's own package id
, useful in DLC code that doesn't know the project name.
DLC: built-in side packages
A DLC is a folder inside your project that contains a
ManagedInfo.toml. ruzit build auto-discovers
them and packages each one alongside the project:
MyGame/
build.toml
Main.luau
assets/
Physics/ # ← DLC folder
ManagedInfo.toml
init.luau
body.luau
assets/
ManagedInfo.toml:
id = "Physics"
name = "Physics DLC"
version = "1.1.0"
creator = "Studio Name"
entry = "init.luau"
"File Type" = "Relative"
include = [
"PhysicsLicense.txt",
"reference-data/",
]
Scaffold a fresh DLC folder with ruzit initpackage Physics.
Native side files: bin/ and include
A DLC folder can ship native libraries and other non-Luau side files just like the host project. Two mechanisms, both convention-driven and merged into the final build:
-
bin/auto-copy. Anything in<dlc>/bin/is copied recursively intoGenerated/bin/alongside the host project's ownbin/. This is where Rust FFI DLLs live; the runtime'sFFI.Loadprobes<exe>/bin/(or<project>/bin/duringruzit test), so the same Luau code works in dev and in the built game. -
includeinManagedInfo.toml. A list of paths (files or folders) relative to the DLC root that are copied verbatim into the exe folder, NOT into a.managedbundle. Use this for third-party SDK DLLs that don't follow the FFI ABI (Steam, EOS, Discord etc.), licenses, or data folders that external tooling reads. Folders replicate recursively with structure preserved.
Physics/ # ← DLC folder
ManagedInfo.toml # declares include = ["PhysicsLicense.txt", ...]
init.luau
bin/
ruzit_physics_solver.dll # → Generated/bin/ruzit_physics_solver.dll
PhysicsLicense.txt # → Generated/PhysicsLicense.txt (via include)
reference-data/
materials.json # → Generated/reference-data/materials.json
bin/, last-write-wins (DLCs first, external folder
packages after). Don't rely on which is which — rename your
DLL to something namespaced (ruzit_ffi_studio_physics.dll)
rather than a generic solver.dll.
External packages: Workshop / mods
Third-party packages live as .managed files in a
Packages/ folder, either in the project root (during
ruzit test) or next to the launcher (after
ruzit build). They're loaded the same way DLC is, but
aren't bundled into the project's launcher, they're drop-ins.
MyGame/
build.toml
Main.luau
Packages/
community-mod.scripts.managed # pre-built bundle
community-mod.assets.managed
ffi-physics-pack/ # loose folder package
ManagedInfo.toml
init.luau
bin/
physics_native.dll
Producers ship their package one of two ways:
-
Pre-built bundle. Run
ruzit packageagainst a folder with aManagedInfo.tomlto produce a pair of.scripts.managed/.assets.managedfiles. Drop those into the project'sPackages/directory. Source stays sealed; nobin/support since the format is a single sealed bundle. -
Loose folder. Drop the package's whole
folder (with its
ManagedInfo.toml,bin/, andincludeentries) intoPackages/.ruzit buildrecompiles it like a DLC and merges itsbin//includeinto the final game. Required when the package needs to ship Rust FFI DLLs or other native side files alongside its scripts.
Patching
With shard-assets = true in build.toml, the
asset bundle splits into ~64 MB shards keyed by content. Patches
only have to re-download the shards whose content changed; the manifest
file lists which assets are in which shard, so the player's launcher
can decide what to fetch.
Scripts always ship as a single .scripts.managed per
package, sharding compiled bytecode rarely pays off.