-
Notifications
You must be signed in to change notification settings - Fork 3
Plugin
Aorux01 edited this page Jan 31, 2026
·
4 revisions
Neodyme features a powerful plugin system that allows you to extend server functionality without modifying the core codebase.
Plugins are loaded from the plugins/ directory and must follow this structure:
class MyPlugin {
// Required properties
name = "MyPlugin";
version = "1.0.0";
description = "A custom plugin for Neodyme";
// Optional: Plugin dependencies
dependencies = [];
/**
* Initialization method - REQUIRED
* @param {PluginManager} pluginManager - The plugin manager instance
* @returns {boolean} - Return true if initialization succeeded
*/
async init(pluginManager) {
try {
// Your initialization code here
LoggerService.log('info', `Plugin ${this.name} initialized successfully`);
return true;
} catch (error) {
LoggerService.log('error', `Failed to initialize ${this.name}: ${error.message}`);
return false;
}
}
/**
* Cleanup method - OPTIONAL but recommended
* Called when plugin is unloaded or server shuts down
*/
async shutdown() {
// Clean up resources, close connections, etc.
LoggerService.log('info', `Plugin ${this.name} shut down`);
}
}
module.exports = MyPlugin;The PluginManager class provides these static methods:
// Load all plugins from plugins/ directory
await PluginManager.load();
// Load a specific plugin by filename (without .js extension)
await PluginManager.loadPlugin("MyCustomPlugin");
// Get list of loaded plugins
const loadedPlugins = PluginManager.getPlugins();// Reload a specific plugin
await PluginManager.reloadPlugin("MyPlugin");
// Reload all plugins
await PluginManager.reload();
// Unload all plugins (usually called on server shutdown)
await PluginManager.unloadAll();class WelcomePlugin {
name = "WelcomePlugin";
version = "1.0.0";
description = "Sends welcome messages to players";
async init(pluginManager) {
// Store reference to plugin manager for later use
this.pluginManager = pluginManager;
// Register event handlers or modify server behavior here
LoggerService.log('success', 'WelcomePlugin loaded - ready to greet players!');
return true;
}
// Example method that could be called from other parts of your code
sendWelcomeMessage(playerId) {
// Your custom logic here
LoggerService.log('info', `Sending welcome to player ${playerId}`);
}
async shutdown() {
LoggerService.log('info', 'WelcomePlugin unloaded');
}
}
module.exports = WelcomePlugin;class DiscordIntegration {
name = "DiscordIntegration";
version = "2.1.0";
description = "Integrates Discord with Neodyme server";
dependencies = [];
async init(pluginManager) {
this.pluginManager = pluginManager;
// Check if Discord bot is enabled in config
if (ConfigManager.get('discordBot')) {
await this.initializeDiscordBot();
}
if (ConfigManager.get('discordWebhook')) {
await this.initializeWebhooks();
}
LoggerService.log('success', 'DiscordIntegration plugin loaded');
return true;
}
async initializeDiscordBot() {
// Discord bot initialization logic
LoggerService.log('info', 'Discord bot integration enabled');
}
async initializeWebhooks() {
// Webhook initialization logic
LoggerService.log('info', 'Discord webhook integration enabled');
}
async shutdown() {
// Clean up Discord connections
LoggerService.log('info', 'DiscordIntegration plugin unloaded');
}
}
module.exports = DiscordIntegration;Plugins can access the server configuration:
const ConfigManager = require('./managers/ConfigManager');
class ConfigurablePlugin {
// ... plugin properties
async init(pluginManager) {
// Read server configuration
const debugMode = ConfigManager.get('debug');
const serverPort = ConfigManager.get('port');
if (debugMode) {
LoggerService.log('info', `Server running on port ${serverPort}`);
}
return true;
}
}LoggerService.log('info', 'Informational message');
LoggerService.log('success', 'Success message');
LoggerService.log('warn', 'Warning message');
LoggerService.log('error', 'Error message');async init(pluginManager) {
try {
// Your initialization code
if (!someRequiredCondition) {
throw new Error('Required condition not met');
}
return true;
} catch (error) {
LoggerService.log('error', `Plugin ${this.name} failed: ${error.message}`);
return false;
}
}class ResourceIntensivePlugin {
constructor() {
this.intervals = [];
this.timeouts = [];
}
async init(pluginManager) {
// Store intervals/timeouts for cleanup
this.intervals.push(setInterval(() => {
this.periodicTask();
}, 60000));
return true;
}
async shutdown() {
// Clean up all intervals and timeouts
this.intervals.forEach(clearInterval);
this.timeouts.forEach(clearTimeout);
LoggerService.log('info', 'Cleaned up all timers');
}
}class DependentPlugin {
name = "DependentPlugin";
version = "1.0.0";
dependencies = ["DatabasePlugin", "AuthPlugin"];
async init(pluginManager) {
const plugins = PluginManager.getPlugins();
const hasDependencies = this.dependencies.every(dep =>
plugins.some(plugin => plugin.name === dep)
);
if (!hasDependencies) {
LoggerService.log('error', `Missing dependencies: ${this.dependencies.join(', ')}`);
return false;
}
return true;
}
}Plugins support hot-reloading during runtime:
// Reload a plugin without restarting the server
const success = await PluginManager.reloadPlugin("WelcomePlugin");
if (success) {
LoggerService.log('success', 'Plugin reloaded successfully');
} else {
LoggerService.log('error', 'Failed to reload plugin');
}-
Discovery: PluginManager scans
plugins/directory for.jsfiles -
Validation: Checks for required
nameandinitmethod -
Initialization: Calls
init()method with PluginManager instance - Runtime: Plugin operates until server shutdown or reload
-
Cleanup:
shutdown()method is called when plugin is unloaded
- Issue: Plugin file has syntax errors
- Solution: Check JavaScript syntax and console for error messages
- Issue: Plugin requires other plugins that aren't loaded
-
Solution: Ensure dependency plugins are loaded first or use
dependenciesarray
- Issue: Plugin doesn't clean up intervals/timeouts
-
Solution: Always implement
shutdown()method to clean resources
Your plugins will automatically load when the server starts if they're placed in the plugins/ directory and follow the required structure.