modlock

module
v0.1.85 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 14, 2026 License: MIT

README

Modlock

Custom game modes for Deadlock, in a language you already know.

Join the Discord Install Publish on hyperline.gg

TypeScript JavaScript Luau Python Go

Modlock lets you write the logic of a Deadlock custom game mode by hand, in TypeScript, JavaScript, Luau, Python or Go, and the game server runs your mod in a WebAssembly sandbox. Every language's library makes its calls to the game as messages from one protobuf schema, so each language gets the same events and calls. modlock publish uploads mods to hyperline.gg, the default platform for custom games.

import { command } from 'modlock'

command('hello', (player) => {
  player.chat('Hello from TypeScript!')
})

Early development. APIs may change without notice between any two releases. TypeScript, JavaScript, Luau, Python and Go mods, the modlock command line and modlock publish all work today.

Getting started

The only program you need is the modlock command. Install it by running the line for your computer.

Windows, in PowerShell:

irm https://raw.githubusercontent.com/paralin/modlock/master/install.ps1 | iex

macOS or Linux, in a terminal:

curl -fsSL https://raw.githubusercontent.com/paralin/modlock/master/install.sh | sh

Or install it with npm on any of them, into a project or globally:

npm install --save-dev @modlock/modlock
npx modlock new my-mod

You need nothing else for a TypeScript, JavaScript, Luau or Python mod, and a Go mod also needs Go. The install page explains how to download modlock by hand and what to do when your terminal cannot find it.

Then make a mod and run it:

modlock new
cd my-mod
modlock dev

modlock new asks for the mod's name and its language. modlock dev builds the mod, starts a local server and launches Deadlock through Steam to join it. Each time you save, it rebuilds the mod and replaces the running one. The starter mod replies to /hello in chat, and Your first mod walks through the rest.

Complete game modes to start from include arena in TypeScript, bounty in Luau and race in Go, all in the examples directory.

Documentation

The documentation is at paralin.github.io/modlock. Every sample there comes in TypeScript, Luau, Python and Go, and once you choose your language, every page shows its samples in it.

Section Holds
Start Install, your first mod, a tutorial and the examples.
Languages What is particular to TypeScript, Luau, Python and Go.
Guides One page for each thing a mod does: events, players, timers, the world.
Mechanics Whole mechanics to start from: a countdown, kill scoring, a hill, a race.
Reference The command line, the manifest and publishing.
Internals The protocol, the framework, building from source and native plugins.

The site's source is in docs, and running bun install and bun run dev there serves it locally. Complete mods to read and run are in examples.

Why WebAssembly

  • Safe to share. A mod runs in a Wasmtime sandbox inside the server, where it can reach only the calls the schema declares. Those calls let it read and write its own files, but it has no network access and no environment variables. When a mod crashes, loops forever or allocates past its limit, the server stops that mod, logs why and keeps the match running. A slow event still finishes, and the players see a warning in chat. Any player can restart a stopped or slow mod with /restartmod.
  • Any language. You can write a mod in any language that compiles to WebAssembly, using a small library for that language.
  • Built once. The server looks up each field and input a mod uses by name, so a mod built before a game update still works after it.
  • Fast. Wasmtime compiles mods to machine code with Cranelift. The server calls a mod inside the game frame and waits for its answer, so the mod can claim a command or change that frame before the game moves on.

Acknowledgments

Thanks to the Deadlock modding community, whose research made this possible. See ATTRIBUTION.md.

License

MIT. See LICENSE.


Questions, ideas or a mod to show off?

Join the Discord

Directories

Path Synopsis
Package binaryen installs Binaryen and optimizes WebAssembly modules with its wasm-opt.
Package binaryen installs Binaryen and optimizes WebAssembly modules with its wasm-opt.
Package boards holds the rules for the boards a mod declares in its manifest: which declarations a build may carry, and which partition values a score may name.
Package boards holds the rules for the boards a mod declares in its manifest: which declarations a build may carry, and which partition values a score may name.
Package check decides whether a built mod may run, without a game.
Package check decides whether a built mod may run, without a game.
cmd
modlock command
Command modlock creates, builds and runs Deadlock mods.
Command modlock creates, builds and runs Deadlock mods.
modlock-entitygen command
Command modlock-entitygen generates the typed entity classes and console of the TypeScript, Go, Luau and Python mod libraries from a game dump, the directory modlock-host --dump writes.
Command modlock-entitygen generates the typed entity classes and console of the TypeScript, Go, Luau and Python mod libraries from a game dump, the directory modlock-host --dump writes.
modlock-library command
Command modlock-library builds the TypeScript library and the interface renderer from this checkout into js/built, which the command line built next embeds:
Command modlock-library builds the TypeScript library and the interface renderer from this checkout into js/built, which the command line built next embeds:
modlock-npm command
Command modlock-npm assembles the npm packages of a Modlock release, in the layout esbuild uses: one package per system holding that system's command line, and @modlock/modlock, which holds the TypeScript library and its declarations and a launcher that runs the command line npm installed for the system it runs on.
Command modlock-npm assembles the npm packages of a Modlock release, in the layout esbuild uses: one package per system holding that system's command line, and @modlock/modlock, which holds the TypeScript library and its declarations and a launcher that runs the command line npm installed for the system it runs on.
modlock-pypi command
Command modlock-pypi assembles the Python wheels of a Modlock release: one wheel per system, each holding that system's command line as a script, so pip install modlock puts modlock on the PATH pip manages:
Command modlock-pypi assembles the Python wheels of a Modlock release: one wheel per system, each holding that system's command line as a script, so pip install modlock puts modlock on the PATH pip manages:
modlock-sdkgen command
Command modlock-sdkgen generates each language's mod library and the host's dispatch from the Host and Mod services in src/wasm/wasm.proto, the single source of the boundary between the game and a mod.
Command modlock-sdkgen generates each language's mod library and the host's dispatch from the Host and Mod services in src/wasm/wasm.proto, the single source of the boundary between the game and a mod.
proto-export command
Command proto-export applies the shared generator's C++ include and build-tag rules.
Command proto-export applies the shared generator's C++ include and build-tag rules.
Package daemon runs one modlock process per state directory that owns the creator's store and peer, and connects the other modlock processes to it.
Package daemon runs one modlock process per state directory that owns the creator's store and peer, and connects the other modlock processes to it.
Package data holds the game data file modlock-host reads at start, so a distribution can ship it apart from the host executable.
Package data holds the game data file modlock-host reads at start, so a distribution can ship it apart from the host executable.
Package devmount owns the package a development session mounts in a Deadlock installation: its directory, its block in gameinfo.gi, and the lock that tells a live session from one that ended without unmounting.
Package devmount owns the package a development session mounts in a Deadlock installation: its directory, its block in gameinfo.gi, and the lock that tells a live session from one that ended without unmounting.
examples
hello-go command
Command hello-go is the smallest Modlock mod in Go: it answers /hello in chat and reports the first server frame.
Command hello-go is the smallest Modlock mod in Go: it answers /hello in chat and reports the first server frame.
hero-build-go command
Command hero-build-go reads a hero's recommended build from the host's game data.
Command hero-build-go reads a hero's recommended build from the host's game data.
race command
Command race is a checkpoint race in Go.
Command race is a checkpoint race in Go.
Package files keeps one mod's files as modlock-host does: the files the mod wrote, in a directory of its own, over the files its build ships in data/.
Package files keeps one mod's files as modlock-host does: the files the mod wrote, in a directory of its own, over the files its build ships in data/.
Package gamelink carries a game's UDP traffic between two PCs over a peer stream.
Package gamelink carries a game's UDP traffic between two PCs over a peer stream.
internal
fetch
Package fetch downloads the tools and releases the modlock command needs into the user cache.
Package fetch downloads the tools and releases the modlock command needs into the user cache.
filelock
Package filelock locks files between processes.
Package filelock locks files between processes.
fileretry
Package fileretry retries a file operation that Windows refuses while another process holds the file for a moment, such as a game reading its configuration, a scanner opening a file just written, or a reader that did not share deletion.
Package fileretry retries a file operation that Windows refuses while another process holds the file for a moment, such as a game reading its configuration, a scanner opening a file just written, or a reader that did not share deletion.
npm
Package npm downloads pinned npm packages into the user cache: the TypeScript checker, the runtime the TypeScript library imports, and the bundler that builds a release.
Package npm downloads pinned npm packages into the user cache: the TypeScript checker, the runtime the TypeScript library imports, and the bundler that builds a release.
prompt
Package prompt asks a person at a terminal for a line of text, one choice from a list, or yes or no.
Package prompt asks a person at a terminal for a line of text, one choice from a list, or yes or no.
selfupdate
Package selfupdate finds newer releases of the modlock command line and installs one over the running executable.
Package selfupdate finds newer releases of the modlock command line and installs one over the running executable.
Package js builds the modlock library that TypeScript and JavaScript mods import: one ES module holding the calls into the game and its protobuf runtime, the entity classes as a second module that imports the first, and their declarations.
Package js builds the modlock library that TypeScript and JavaScript mods import: one ES module holding the calls into the game and its protobuf runtime, the entity classes as a second module that imports the first, and their declarations.
Package lfs keeps Git LFS objects in the PC's local Space.
Package lfs keeps Git LFS objects in the PC's local Space.
Package luau holds the modlock library that Luau mods require as "@modlock", and downloads the analyzer that type checks them.
Package luau holds the modlock library that Luau mods require as "@modlock", and downloads the analyzer that type checks them.
Package metrics holds the rules for the metrics a mod declares in its manifest: which declarations a build may carry, which labels a call may name, and how each kind combines the values added to it.
Package metrics holds the rules for the metrics a mod declares in its manifest: which declarations a build may carry, which labels a call may name, and how each kind combines the values added to it.
mod
Package mod writes Modlock mods in Go.
Package mod writes Modlock mods in Go.
console
Package console sets the server's console variables and runs its console commands, through values modlock-entitygen generates from the game's console:
Package console sets the server's console variables and runs its console commands, through values modlock-entitygen generates from the game's console:
entity
Package entity reads and writes the fields of live entities, sends them inputs and creates them, through typed classes generated from the game's schema and entity dump by modlock-entitygen.
Package entity reads and writes the fields of live entities, sends them inputs and creates them, through typed classes generated from the game's schema and entity dump by modlock-entitygen.
hud
Package hud draws a mod's HUD in the stock HUD's look, from the tokens in package theme.
Package hud draws a mod's HUD in the stock HUD's look, from the tokens in package theme.
theme
Package theme holds the HUD kit's tokens, each named once: the colors, type scale and sizes the kit's components draw with, and that a mod's own panels can share.
Package theme holds the HUD kit's tokens, each named once: the colors, type scale and sizes the kit's components draw with, and that a mod's own panels can share.
ui
Package ui draws each player's interface from a tree of elements, as struct literals:
Package ui draws each player's interface from a tree of elements, as struct literals:
Package panorama holds the renderer that draws mods' interfaces in the player's game.
Package panorama holds the renderer that draws mods' interfaces in the player's game.
Package peernet runs a modlock peer: a PC's key on Spacewave's peer network, which links directly to other PCs over WebRTC.
Package peernet runs a modlock peer: a PC's key on Spacewave's peer network, which links directly to other PCs over WebRTC.
Package preview serves the page modlock dev opens beside a running mod: it draws every screen the mods show the local player with the game's own drawing on a browser stand-in for Panorama, says what the build and the mods are doing, and passes the page's presses and chat commands to the mods as that player's input.
Package preview serves the page modlock dev opens beside a running mod: it draws every screen the mods show the local player with the game's own drawing on a browser stand-in for Panorama, says what the build and the mods are doing, and passes the page's presses and chat commands to the mods as that player's input.
Package project reads, creates and builds mod source projects.
Package project reads, creates and builds mod source projects.
Package publish hands a built mod to a provider: hyperline.gg, an archive players unpack and run, or a GitHub release that holds the archive.
Package publish hands a built mod to a provider: hyperline.gg, an archive players unpack and run, or a GitHub release that holds the archive.
Package python holds the modlock library that Python mods import as modlock, and downloads the Pyright checker and the Node.js that runs it.
Package python holds the modlock library that Python mods import as modlock, and downloads the Pyright checker and the Node.js that runs it.
Package runtimes builds the interpreted runtimes' modules outside the C++ build, for a command line that must run a script mod as the host does but has no host package at hand.
Package runtimes builds the interpreted runtimes' modules outside the C++ build, for a command line that must run a script mod as the host does but has no host package at hand.
Package sandbox runs built mods without a game.
Package sandbox runs built mods without a game.
Package scriptc downloads the scriptc compiler and fits a module it compiled as a WASI reactor to the mod boundary, so the host runs it as it runs any other mod.
Package scriptc downloads the scriptc compiler and fits a module it compiled as a WASI reactor to the mod boundary, so the host runs it as it runs any other mod.
Package session runs a play session: modlock-host with the mods, a Deadlock client that joins it, and the control link that reports the mods' progress and reloads them.
Package session runs a play session: modlock-host with the mods, a Deadlock client that joins it, and the control link that reports the mods' progress and reloads them.
Package settings holds the rules for the settings a mod declares in its manifest: which declarations a build may carry, which values each setting accepts, and the value a player starts with.
Package settings holds the rules for the settings a mod declares in its manifest: which declarations a build may carry, which values each setting accepts, and the value a player starts with.
source2
gameinfo
Package gameinfo edits the search paths in a Source 2 game's gameinfo.gi, which several programs share: Steam, mod managers and tools that mount content for a while.
Package gameinfo edits the search paths in a Source 2 game's gameinfo.gi, which several programs share: Steam, mod managers and tools that mount content for a while.
kv3
Package kv3 reads binary KeyValues3 versions 4 and 5 and writes version 5, the format Source 2 compiled resources store their data in.
Package kv3 reads binary KeyValues3 versions 4 and 5 and writes version 5, the format Source 2 compiled resources store their data in.
panorama
Package panorama compiles Panorama layouts, scripts and style sheets into the resources the game loads, without Valve's resource compiler, and decompiles layouts back to XML and style sheets back to CSS.
Package panorama compiles Panorama layouts, scripts and style sheets into the resources the game loads, without Valve's resource compiler, and decompiles layouts back to XML and style sheets back to CSS.
resource
Package resource reads and writes the container of a Source 2 compiled resource, such as a .vxml_c layout or a .vents_c entity lump: a header and a table of tagged blocks, each holding one part of the resource.
Package resource reads and writes the container of a Source 2 compiled resource, such as a .vxml_c layout or a .vents_c entity lump: a header and a table of tagged blocks, each holding one part of the resource.
vpk
Package vpk reads and writes Valve archives (VPK), the packages Source 2 games mount their resources from.
Package vpk reads and writes Valve archives (VPK), the packages Source 2 games mount their resources from.
vpk/vpktest
Package vpktest writes small Valve archives for tests.
Package vpktest writes small Valve archives for tests.
Package sourcemap reads version 3 source maps, as bundlers write them beside a script, to find where a place in the bundle came from.
Package sourcemap reads version 3 source maps, as bundlers write them beside a script, to find where a place in the bundle came from.
Package space holds a PC's local Space: a World on a database in the daemon's directory.
Package space holds a PC's local Space: a World on a database in the daemon's directory.
src
Package studio serves Modlock Studio: one web page, built with the Modlock library, whose first workspace browses and draws the game's own assets from the player's install.
Package studio serves Modlock Studio: one web page, built with the Modlock library, whose first workspace browses and draws the game's own assets from the player's install.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL