Plugin Architecture: Audio System

This guide demonstrates how to create a "pop-in" plugin that listens for game events and triggers audio, maintaining strict separation of concerns.

1. The Design Principle

The core engine does not contain a "play sound" function inside the combat logic. Instead, the combat logic emits an event. The Audio Plugin sits in the background, listening for that specific event, and plays the sound when it hears it.

2. The Plugin Implementation

// plugins/AudioPlugin.js
export const AudioPlugin = {
    id: 'audio-system',
    
    // The engine calls this upon loading the plugin
    init(eventBus, assetManager) {
        this.eventBus = eventBus;
        this.assetManager = assetManager;

        // Listen for global game events
        this.eventBus.on('ENTITY_DIED', (data) => {
            this.playSound('explosion_01.mp3');
        });

        this.eventBus.on('PLAYER_JUMP', () => {
            this.playSound('jump_sfx.ogg');
        });
    },

    playSound(fileName) {
        // Access pre-loaded audio buffers from the asset manager
        const sound = this.assetManager.getAudio(fileName);
        sound.play();
    }
};

3. How it "Pops In"

Because the plugin follows a standard interface (the init function), the core engine's loader handles it automatically:

// Core Engine Loader
async function loadPlugins() {
    const pluginFiles = ['plugins/AudioPlugin.js', 'plugins/RendererPlugin.js'];
    
    for (const path of pluginFiles) {
        const { plugin } = await import(path);
        // Inject the Event Bus so the plugin can "talk" to the rest of the game
        plugin.init(globalEventBus, globalAssetManager);
    }
}

4. Key Benefits