import "reflect-metadata"; import { CoreProperties as PackageJson } from "@schemastore/package"; import { BaseRole } from "@skeldjs/core"; import { Deserializable } from "@skeldjs/protocol"; import { Room, Worker } from "../worker"; import { PluginRegisteredMatchmakerEndpoint, PluginRegisteredMessageHandlerInfo, RegisteredPrefab } from "../api"; import { PluginDependencyDeclaration } from "../api/hooks/Dependency"; import { PluginInstanceType, RoomPlugin, SomePluginCtr, WorkerPlugin } from "./Plugin"; import vorpal from "vorpal"; export declare const hindenburgPluginDirectory: unique symbol; export interface PluginPackageJsonOptions { loadOrder?: "first" | "last" | "none" | number; defaultConfig?: any; dependencies?: Record>>; } export interface PluginPackageJson extends PackageJson { plugin?: PluginPackageJsonOptions; } export declare class ImportedPlugin { protected readonly pluginLoader: PluginLoader; readonly pluginCtr: PluginCtr; readonly localDirectory: string; readonly packageJson: PluginPackageJson; protected _cachedPackageJson?: PluginPackageJson; static getPluginPackageJson(pluginPath: string): Promise; static importPlugin(pluginLoader: PluginLoader, pluginPath: string): Promise>; constructor(pluginLoader: PluginLoader, pluginCtr: PluginCtr, localDirectory: string, packageJson?: PluginPackageJson); isWorkerPlugin(): this is ImportedPlugin; isRoomPlugin(): this is ImportedPlugin; isEnabled(room?: Room): boolean | undefined; getDependencies(): { [x: string]: boolean | Partial>; }; } export declare class LoadedPlugin { readonly importedPlugin: ImportedPlugin; readonly pluginInstance: PluginInstanceType; /** * All chat commands that were loaded into the room, created with {@link ChatCommand}. */ loadedChatCommands: string[]; /** * All CLI commands that were loaded into the worker, created with {@link CliCommand}. */ loadedCliCommands: vorpal.Command[]; /** * All event listeners that were loaded into the worker, created with {@link EventListener}. */ loadedEventListeners: { eventName: string; handler: (...args: any) => any; }[]; /** * All protocol message handlers that were loaded into the worker, created with * {@link MessageHandler}. */ loadedMessageHandlers: PluginRegisteredMessageHandlerInfo[]; /** * All registered http endpoints to be hosted on the http matchmaker, created with * {@link MatchmakerEndpoint}. */ loadedMatchmakerEndpoints: PluginRegisteredMatchmakerEndpoint[]; /** * All protocol messages that were registered into the worker, created with * {@link RegisterMessage}. */ loadedRegisteredMessages: Deserializable[]; /** * All registered spawn prefabs for the plugin, created with {@link RegisterPrefab}. */ registeredPrefabs: RegisteredPrefab[]; /** * All registered player roles for the plugin, created with {@link RegisterRole}. */ registeredRoles: typeof BaseRole[]; constructor(importedPlugin: ImportedPlugin, pluginInstance: PluginInstanceType); isWorkerPlugin(): this is LoadedPlugin; isRoomPlugin(): this is LoadedPlugin; } /** * Service for the worker node to import plugins & load them globally or into * specific rooms. * * An "imported plugin" is a plugin which has actually been loaded into memory * with require(), and a "loaded plugin" is a plugin which is enabled on a room * or globally. */ export declare class PluginLoader { /** * The worker that this plugin loader is for. */ readonly worker: Worker; /** * The base directory for installed plugins. */ readonly pluginDirectories: string[]; /** * A map of every worker and room plugin that has been imported. */ importedPlugins: Map; /** * Create a plugin loader. Note that the worker instantiates one itself, see * {@link Worker.pluginLoader}. * @param worker The worker that the plugin loader is for. * @param pluginDirectories The base directory for installed plugins. * @example * ```ts * const pluginLoader = new PluginLoader(this.worker, "/home/user/hindenburg/plugins"); * ``` */ constructor( /** * The worker that this plugin loader is for. */ worker: Worker, /** * The base directory for installed plugins. */ pluginDirectories: string[]); /** * Check whether some object is a Hindenburg plugin. * @param someObject The object to check. * @returns Whether {@link someObject} is a Hindenburg plugin. * * @example * ```ts * console.log(this.worker.pluginLoader.isHindenburgPlugin({})); // false * ``` * * @example * ```ts * class MyPlugin extends WorkerPlugin {} * * console.log(this.worker.pluginLoader.isHindenburgPlugin(MyPlugin)); // true * ``` */ static isHindenburgPlugin(someObject: any): boolean; /** * Check whether an imported Hindenburg plugin is a worker plugin to be loaded * globally, extending {@link WorkerPlugin}. * @param pluginCtr The plugin to check. * @returns Whether {@link pluginCtr} is a global worker plugin. * * @example * ```ts * .@HindenburgPlugin("hbplugin-fun-things") * class MyPlugin extends RoomPlugin {} * * console.log(this.worker.pluginLoad.isWorkerPlugin(MyPlugin)); // false * ``` * * @example * ```ts * .@HindenburgPlugin("hbplugin-fun-things") * class MyPlugin extends WorkerPlugin {} * * console.log(this.worker.pluginLoad.isWorkerPlugin(MyPlugin)); // true * ``` */ static isWorkerPlugin(pluginCtr: SomePluginCtr): pluginCtr is typeof WorkerPlugin; /** * Check whether an imported Hindenburg plugin is a room plugin to be loaded * into rooms, extending {@link RoomPlugin}. * @param pluginCtr The plugin to check. * @returns Whether {@link pluginCtr} is a room plugin. * * @example * ```ts * .@HindenburgPlugin("hbplugin-fun-things") * class MyPlugin extends RoomPlugin {} * * console.log(this.worker.pluginLoad.isRoomPlugin(MyPlugin)); // true * ``` * * @example * ```ts * .@HindenburgPlugin("hbplugin-fun-things") * class MyPlugin extends WorkerPlugin {} * * console.log(this.worker.pluginLoad.isRoomPlugin(MyPlugin)); // false * ``` */ static isRoomPlugin(pluginCtr: SomePluginCtr): pluginCtr is typeof RoomPlugin; /** * Generate a random plugin ID. * * Note that this will return one even if it is taken, see {@link PluginLoader.generateRandomPluginIdSafe} * if you need one that is not taken. * @returns A random plugin ID. */ static generateRandomPluginId(): string; /** * Import a plugin via its ID, checking both installed NPM plugins and also * local plugin folders. * @param id The ID of the plugin to import. * @returns The loaded plugin, or 'undefined' if unsuccessful (e.g. the * module could not be found, or it was loaded but it was not a Hindenburg * plugin). * * @example * ```ts * const pluginCtr = await this.worker.pluginLoader.importFromId("hbplugin-fun-things"); * * if (!pluginCtr) { * console.log("Failed to load my plugin."); * return; * } * ``` */ importFromId(id: string): Promise | undefined>; /** * Import all plugins from the {@link PluginLoader.pluginDirectories}, from * both installed NPM plugins and local plugin folders. * * Does not load any of the plugins into the worker or a room, see {@link * PluginLoader.loadAllWorkerPlugins} and {@link PluginLoader.loadAllRoomPlugins}. * @returns A map of all plugins that were imported. * * @example * ```ts * const importedPlugins = this.worker.pluginDirectory.importFromDirectory(); * * console.log("Imported %s plugins!", importedPlugins.size); * ``` */ importFromDirectories(): Promise>>; protected sortPlugins(pluginCtrs: ImportedPlugin[]): void; protected visitAndLoadPlugin(graph: ImportedPlugin[], visited: Map, tree: Set, node: ImportedPlugin, room?: Room): Promise; /** * Load all imported worker plugins into the worker, checking {@link PluginLoader.isEnabled}. * @example * ```ts * await this.worker.pluginLoader.loadAllWorkerPlugins(); * ``` */ loadAllWorkerPlugins(): Promise; /** * Load all imported room plugins into a room, checking {@link PluginLoader.isEnabled}. * @example * ```ts * await this.worker.pluginLoader.loadAllWorkerPlugins(); * ```7 */ loadAllRoomPlugins(room: Room): Promise; /** * Generate a random plugin ID that has not been taken by any other plugins. * @returns A random plugin ID that can safely be used. */ generateRandomPluginIdSafe(): string; /** * Import a plugin from its absolute path on the filesystem. * @param pluginPath The path of the plugin to import. * @returns The imported plugin constructor, or false if the plugin failed * to be imported or was not a Hindenburg plugin. * * @example * ```ts * const pluginCtr = await this.worker.pluginLoader.importPlugin("/home/user/hindenburg/plugins/hbplugin-fun-things"); * * if (!pluginCtr) { * console.log("Failed to load my plugin!"); * return; * }x * ``` */ importPlugin(pluginPath: string): Promise; private applyChatCommands; private applyRegisteredPrefabs; private applyRegisteredRoles; private applyRegisteredMessages; private applyMessageHandlersPlugin; private applyMessageHandlers; /** * Load a global worker plugin into the worker, does not regard {@link PluginLoader.isEnabled}, * waits for {@link Plugin.onPluginLoad} to be finish. * @param pluginCtr The plugin ID or class to load. * @returns The plugin instance that was loaded. * @throws If there was an attempt to load a plugin that isn't imported, or * if the server tries load a worker plugin onto a room. * * @example * ```ts * const importedPlugin = await this.worker.workerPlugins.get("hbplugin-fun-things"); * await this.worker.pluginLoader.loadPlugin(importedPlugin); * ``` * * @example * ```ts * const importedPlugin = await this.worker.workerPlugins.get("hbplugin-fun-things"); * await this.worker.pluginLoader.loadPlugin(importedPlugin, this.room); // !! Attempted to load a worker plugin on a room or other non-worker object * ``` * * @example * ```ts * await this.worker.pluginLoader.loadPlugin("hbplugin-what-the-hell"); // !! Plugin with ID 'hbplugin-what-the-hell' not imported * ``` */ loadPlugin(pluginCtr: string | ImportedPlugin): Promise; /** * Load a room plugin into a room, does not regard {@link PluginLoader.isEnabled}, * waits for {@link Plugin.onPluginLoad} to be finish. * @param pluginCtr The plugin ID or class to load. * @param room The room to load the plugin into. * @returns The plugin instance that was loaded. * @throws If there was an attempt to load a plugin that isn't imported, or * if the server tries load a room plugin onto the worker. * * @example * ```ts * const importedPlugin = await this.worker.roomPlugins.get("hbplugin-fun-things"); * await this.worker.pluginLoader.loadPlugin(importedPlugin, this.room); * ``` * * @example * ```ts * const importedPlugin = await this.worker.roomPlugins.get("hbplugin-fun-things"); * await this.worker.pluginLoader.loadPlugin(importedPlugin); // !! Attempted to load a room plugin on a worker or other non-room object * ``` * * @example * ```ts * await this.worker.pluginLoader.loadPlugin("hbplugin-what-the-hell", this.room); // !! Plugin with ID 'hbplugin-what-the-hell' not imported * ``` */ loadPlugin(pluginCtr: string | ImportedPlugin, room: Room): Promise; /** * Unload a global worker plugin from the worker, calls but doesn't wait for * {@link Plugin.onPluginUnload} to finish. * @param pluginCtr The plugin ID, class, or instance to unload. * @throws If there was an attempt to unload a plugin that isn't loaded. * @example * ```ts * this.worker.pluginLoader.unloadPlugin("hbplugin-fun-things"); * ``` * * @example * ```ts * this.worker.pluginLoader.unloadPlugin("hbplugin-what-the-hell"); // !! Plugin with id 'hbplugin-what-the-hell' not loaded * ``` */ unloadPlugin(pluginCtr: string | WorkerPlugin | typeof WorkerPlugin): void; /** * Unload a room plugin from a room, calls but doesn't wait for * {@link Plugin.onPluginUnload} to finish. * @param pluginCtr The plugin ID, class, or instance to unload. * @param room The room to unload the plugin from. * @throws If there was an attempt to unload a plugin that isn't loaded. * @example * ```ts * this.worker.pluginLoader.unloadPlugin("hbplugin-fun-things"); * ``` * * @example * ```ts * this.worker.pluginLoader.unloadPlugin("hbplugin-what-the-hell"); // !! Plugin with id 'hbplugin-what-the-hell' not loaded * ``` */ unloadPlugin(pluginCtr: string | RoomPlugin | typeof RoomPlugin, room: Room): void; }