Skip to main content

Quick Start: Development Guide

This guide is for developers who want to extend NodeMod. There are two ways to add functionality:

  1. NodeMod Scripts — Write any Node.js code, import it in the main entry point
  2. Admin System Plugins — Create AMX Mod X-style plugins with permissions, help integration, etc.
Already Installed?

NodeMod comes with a complete AMX Mod X admin system that works immediately after installation. This guide is for developers who want to add custom functionality.

Prerequisites

  • NodeMod installed on your server
  • Node.js 18+ on your development machine
  • Basic JavaScript/TypeScript knowledge

Option 1: NodeMod Scripts (Simple)

NodeMod is just Node.js — it runs whatever file is specified in package.json under "main". You can write any Node.js code and import it.

How It Works

addons/nodemod/plugins/
├── package.json # "main": "dist/index.js"
├── src/
│ ├── index.ts # Entry point - imports everything
│ ├── admin/ # Admin system (already included)
│ └── myscript.ts # ← Your custom scripts go here
└── dist/ # Compiled JavaScript

Creating a Custom Script

Step 1: Create your script file src/myscript.ts:

import nodemodCore from '@nodemod/core';

console.log('[MyScript] Loading...');

// Register a command
nodemodCore.cmd.registerClient('hello', (client, args) => {
if (!client) return;
nodemodCore.util.messageClient(client, `Hello, ${client.netname}!`);
});

// React to events
nodemodCore.events.on('dllClientPutInServer', (entity) => {
nodemodCore.util.sendChat(`Welcome ${entity.netname}!`, null);
});

console.log('[MyScript] Loaded!');

Step 2: Import it in src/index.ts:

import './admin';      // Admin system
import './myscript'; // Your custom script

Step 3: Build and restart:

cd addons/nodemod/plugins
npm run build
# Restart server

When to Use This

  • Simple commands or features
  • One-off scripts
  • Features that don't need admin permissions
  • Quick prototypes

The admin system has its own plugin loader with features like:

  • Permission-based access control
  • Automatic help system integration (amx_help)
  • Localization support
  • Plugin metadata and lifecycle hooks

How It Works

addons/nodemod/
├── configs/
│ └── plugins.ini # Lists which admin plugins to load
└── plugins/src/admin/
├── index.ts # Admin system entry point
├── pluginloader.ts # Loads plugins from plugins.ini
├── baseplugin.ts # Base class for plugins
├── admin.ts # Core admin (kick, ban, etc.)
├── admincmd.ts # Admin commands
└── myplugin.ts # ← Your admin plugins go here

Creating an Admin Plugin

Step 1: Create your plugin src/admin/myplugin.ts:

import { BasePlugin } from './baseplugin';
import { Plugin, PluginMetadata } from './pluginloader';
import { ADMIN_CHAT } from './constants';
import { adminSystem } from './admin';

class MyPlugin extends BasePlugin implements Plugin {
readonly metadata: PluginMetadata = {
name: 'My Plugin',
version: '1.0.0',
author: 'Your Name',
description: 'My custom admin plugin'
};

constructor(pluginName: string) {
super(pluginName);

// Register admin command (appears in amx_help)
this.registerCommand('amx_greet', ADMIN_CHAT, '<player> - Greet a player',
(entity, args) => this.cmdGreet(entity, args));
}

private cmdGreet(admin: nodemod.Entity | null, args: string[]) {
// Check permission
if (!adminSystem.cmdAccess(admin, ADMIN_CHAT)) return;

if (args.length < 1) {
this.sendConsole(admin, 'Usage: amx_greet <player>');
return;
}

const target = adminSystem.cmdTarget(admin, args[0], 0);
if (!target) return;

// Show activity to players (respects amx_show_activity)
this.showActivity(admin, `greeted ${target.netname}`);

// Log action
this.logAmx(`Greet: "${this.getAdminName(admin)}" greeted "${target.netname}"`);
}
}

// Export as default for plugin loader
export default MyPlugin;

Step 2: Add to configs/plugins.ini:

; Core plugins
admin
admincmd
adminhelp

; My custom plugin
myplugin

Step 3: Build and restart:

cd addons/nodemod/plugins
npm run build
# Restart server

When to Use This

  • Commands that need admin permissions
  • Features that should appear in amx_help
  • Plugins that need player targeting with immunity
  • Features requiring activity logging
  • Multi-language support

Learn More About Admin Plugins


Core API Quick Reference

Commands

// Simple client command
nodemodCore.cmd.registerClient('mycommand', (client, args) => {
if (!client) return;
// client is the player entity, args is string[]
});

Events

// Player events
nodemodCore.events.on('dllClientConnect', (entity, name, address) => {});
nodemodCore.events.on('dllClientPutInServer', (entity) => {});
nodemodCore.events.on('dllClientDisconnect', (entity) => {});

// Server events
nodemodCore.events.on('dllServerActivate', (edict, edictCount, maxClients) => {});

Messaging

// To one player
nodemodCore.util.messageClient(client, 'Hello!');

// To all players
nodemodCore.util.sendChat('Announcement!', null);

Players

// Get all players
const players = nodemodCore.player.getAll();

// Entity properties
client.netname; // Player name
client.health; // Health
client.origin; // [x, y, z] position

Development Workflow

# Terminal 1: Auto-rebuild on save
cd addons/nodemod/plugins
npm run dev

# Terminal 2: Run server
./hlds_linux -game valve +map crossfire

Changes require a server restart to take effect.


More Resources

Troubleshooting

Build errors?

npx tsc --noEmit  # Check for TypeScript errors

Script not loading?

  • Ensure you imported it in src/index.ts
  • Check for errors in server console

Admin plugin not loading?

  • Verify it's listed in configs/plugins.ini
  • Check plugin exports default class
  • Look for errors in server console