Plugin Development
Audience: Developers extending LegacyShell · Prereqs: JavaScript, Running a Server
LegacyShell's stated philosophy is "could this be a plugin?" - most new functionality, from a single chat command to a full anticheat, is meant to be built as a plugin rather than patched into core. This section teaches the plugin API from a working "hello world" up through the patterns real, shipped plugins use.
Not sure where to start, or looking for a specific answer rather than a linear read-through? I Want To... is a task-oriented index of this entire section, phrased as goals ("I want to add a new weapon," "I want my plugin's data to survive a restart") with a direct link to the right page for each.
What's here
- Quickstart - a working plugin in ten minutes.
- Anatomy - the folder contract,
PluginMeta, thePluginclass, disabling a plugin with a leading_. - Lifecycle - load order, alphabetical sorting, git auto-pull on load, gating a plugin to one server type.
- Dependencies -
dependencies.js, npm packages vs. depending on another plugin. - Events (concept) -
on/emit, thetype:prefix system, payload shapes, the sharedplugins.cancelflag. - Event Reference - the full, generated table of every event LegacyShell emits (~185 of them), split by subsystem.
- Commands - hooking
permissionsAfterSetup,newCommand, permission tuples, @mentions. - Client-side code - shipping browser JS via
pluginSourceInsertion, theisClientguard. - Static assets - serving your plugin's own files via
onStartServer. - Content packs - shipping items, maps, and models from a plugin.
- Networking - registering new wire-protocol opcodes with
Comm.Add. - Workers and state - the worker-per-room isolation gotcha, and using
wsrequestfor state that needs to cross rooms. - Prediction and authority - why most nontrivial gameplay code needs both an
executeClientand anexecuteServerhalf. - Modifiers - the per-team gameplay multipliers (speed, gravity, damage, and a dozen others) behind both gamemodes and the
changeslash commands. - Sound and Apollo - registering and playing sounds from a plugin via LegacyShell's Howler.js wrapper.
- Recipes - complete worked examples: killstreaks, a new gamemode, a custom weapon, a new pickup item, UI changes, a custom theme, Discord integration, persistent storage, player currency, custom per-player data, and replacing core behavior outright.
- Publishing - versioning a plugin and listing it publicly.
- Pitfalls - the mistakes real plugins in this repo have actually made (a shared cancel flag stepping on another plugin, listening for events that don't exist, assuming state persists across worker threads).
For the deeper "how does the engine actually work" material this section builds on, see Codebase Reference.
This page was drafted with AI assistance and reviewed for accuracy. If something looks wrong, please open a PR or flag it.
