LegacyShell WikiLegacyShell Wiki
Back to LegacyShell
Home
Wiki
Plugins
Docs
Back to LegacyShell
Home
Wiki
Plugins
Docs
  • Documentation

    • Getting Started

      • What is LegacyShell?
      • Speed Setup
      • Requirements
      • Installation
      • First Run
      • Config Files
      • Making an Account
      • Troubleshooting (Getting Started)
    • Running a Server

      • Architecture Overview
      • The Database
      • Users and Ranks
      • Adding Game Servers
      • Client Mirrors
      • Perpetual
      • Backups
      • Rate Limiting
      • Moderation
      • Closed Mode
      • Deployment
      • Troubleshooting (Running a Server)
      • Hosting for Someone Else's Instance
    • Content Creation

      • Maps
      • Dealing with Babylon Models
      • Map Blocks
      • Items and Skins
      • Hats and Stamps
      • Sounds
      • Gamemodes
      • Seasonal Events
    • Plugin Development

      • Quickstart
      • I Want To...
      • Anatomy of a Plugin
      • Lifecycle
      • Dependencies
      • Events (Concept)
      • Event Reference

        • services: events
        • game: events — shared logic (src/shell/)
        • game: events — main-thread server process
        • game: events — per-connection client object
        • game: events — room lifecycle & tick loop
        • game: events — in-browser gameplay
        • client: events — client server & build pipeline
      • Commands
      • Client-Side Code
      • Static Assets
      • Content Packs
      • Networking
      • Workers and State
      • Prediction and Authority
      • Recipes

        • Recipe: Killstreaks
        • Recipe: New Pickup Item
        • Recipe: New Gamemode
        • Recipe: Custom Weapon
        • Recipe: UI Modification
        • Recipe: Discord Integration
        • Recipe: Replacing Core Behaviour
        • Recipe: Persistent Plugin Storage
        • Recipe: Rewarding Players with Currency
        • Recipe: Custom Per-Player Data
        • Recipe: Custom Theme
      • Publishing
      • Pitfalls
      • Modifiers
      • Sound and Apollo
    • Codebase Reference

      • Repo Layout
      • Shared Shell Layer
      • Server-Only Markers
      • The ss Object
      • Build Pipeline
      • Stamps and Babylons
      • Game Loop
      • Rooms and Workers
      • Wire Protocol
      • Generated

        • Wire Protocol Opcodes
        • Enums & Lookup Tables
        • Database Schema
        • Config Reference
        • Slash Command Reference
      • Services Internals
      • Catalog and Items
      • Permissions Internals
      • Physics and Collision
      • Known Quirks
      • Codebase Anecdotes
      • Development Timeline
    • Contributing

      • Documentation Style Guide
      • Generators
      • For AI Agents

Quickstart

Audience: Plugin authors · Prereqs: Running a Server, basic JavaScript

Canonical source: src/shell/plugins.js (PluginManager), plugins_samples/sample1cmd/

A working LegacyShell plugin in about ten minutes: a folder, two files, one restart.

1. Create the folder

Plugins live in plugins/ (for your own/third-party plugins - plugins_default/ is reserved for the ones LegacyShell ships with). Create:

plugins/hello-legacyshell/

The folder name doesn't have to match anything inside it, but keep it lowercase and hyphenated - it's what shows up in boot logs and in dependency declarations from other plugins.

2. Write index.js

Every plugin needs exactly one required file: index.js, exporting a PluginMeta object and a Plugin class.

// plugins/hello-legacyshell/index.js
import log from 'puppylog';

export const PluginMeta = {
    identifier: "hellolegacyshell",
    name: 'Hello LegacyShell',
    author: 'you',
    version: '1.0.0',
    descriptionShort: 'Says hello when the game server starts.',
    descriptionLong: 'A minimal example plugin for the quickstart guide.',
    legacyShellVersion: 598, // see /versionEnum.txt
};

export class Plugin {
    constructor(plugins, thisDir) {
        this.plugins = plugins;
        this.thisDir = thisDir;

        if (plugins.type !== "game") {
            log.orange(`${PluginMeta.identifier} won't run on this server type.`);
            return;
        };

        this.plugins.on('game:startUp', this.onStartUp.bind(this));
    };

    onStartUp(data) {
        log.green("Hello from a plugin! (This actually fires in the browser, not the Node server - see below.)");
    };
};

That's the entire contract: PluginMeta (metadata) and Plugin (a class, instantiated once as new Plugin(pluginManager, pluginFolderPath)). Everything else - registering event listeners, adding commands, shipping browser code - happens inside that constructor or methods it calls.

Why game:startUp fires in the browser, not on your Node server

startUp is emitted from the shared game-logic source that gets spliced into the browser bundle (see Events (concept)), not from server-game's own boot sequence. It's a deliberately chosen "does this even work" test event for the quickstart, precisely because it's easy to eyeball in a browser console. For something that actually fires in your Node terminal on boot, use game:roomInit or services:servicesOnLoad instead - see the Event Reference once it's built out.

3. Restart the affected server(s)

Plugins load once at server startup - there's no hot reload. Restart whichever server(s) this plugin targets (here, game):

npm run game

Watch the boot log - you should see your plugin listed and loaded:

Starting plugin -> hellolegacyshell
Loaded plugin -> Hello LegacyShell v1.0.0 by you: Says hello when the game server starts.

If it doesn't show up, double-check the folder name doesn't start with _ (that disables it - see Anatomy) and that index.js doesn't have a syntax error (check the boot log for a stack trace).

4. See it actually do something

Since game:startUp fires client-side, open the browser console (F12) at http://localhost:13370 and load into a game - you'll see the green log line there, not in your terminal. This is the fastest possible way to confirm your plugin is genuinely loaded and wired up correctly end to end (config → server → build → browser), before you write anything that actually changes gameplay.

Where to go next

  • Anatomy - the full folder contract and PluginMeta schema, in detail.
  • Events (concept) - how on/emit actually work, and the full list of events available.
  • Commands - adding your own slash commands, probably the most common first real thing to build.
  • The Recipes section has complete, working examples if you'd rather learn by reading a finished plugin than building one from scratch.
  • I Want To... - if you already know what you're trying to build, this task-oriented index jumps straight to the relevant page instead of reading through the whole section.
  • For real, currently-shipping plugins to read (rather than the deliberately minimal examples on this page), browse plugins_default/ and plugins_samples/ directly - not plugins/, which is empty on a fresh install. See I Want To... for pointers on which bundled plugin demonstrates what.

This page was drafted with AI assistance and reviewed for accuracy. If something looks wrong, please open a PR or flag it.

Edit this page on GitHub
Next
I Want To...