00 — the basics

Welcome

Welcome to the Raton Plugin Guide. This guide walks you through everything needed to create, test, and publish plugins that extend Raton's functionality. Plugins are compiled C# assemblies loaded at runtime — they can receive arguments from the UI and communicate back through a structured packet system.

Quick start
1
Create a new .NET Class Library project targeting .NET Framework 4.7.2
2
Use the test plugin source to guide yourself
3
Decorate your class with [PluginInfo] and implement Main
4
Compile, drop the .dll into Raton's /plugins folder
5
Enjoy :)
01 — project structure

Project Structure

Your plugin is a standard .NET Class Library project. Raton discovers it as a compiled DLL. Minimum layout:

folder structure
MyPlugin/ ├── MyPlugin.csproj ├── Main.cs └── Networking/ └── Default classes
ℹ
Tip: Set output type to Class Library in your .csproj so the compiler emits a .dll instead of an .exe.
02 — [plugininfo] attribute

[PluginInfo] Attribute

Every plugin class must be decorated with [PluginInfo]. Raton reads this to register your plugin in the UI and display a description to the user.

PluginInfoAttribute.cs
using System;
[AttributeUsage(AttributeTargets.Class)]
public class PluginInfoAttribute : Attribute
{
    public string Description { get; }
    public string Provider    { get; }

    public PluginInfoAttribute(string description)
    {
        Provider    = "Raton";
        Description = description;
    }
}
⚠
Warning: Never change Provider = "Raton". Raton uses this field to verify the plugin origin.

Usage on your own class:

Program.cs
[PluginInfo("Example plugin for testing")]
class Program
{
    // ...
}
03 — entry point

Entry Point: Main

Raton calls a static Main method on your class, the signature is different. Raton injects two parameters:

Action<byte[]> sendDelegate to send a serialized Pack back to the client. Store it in a static field.
string[] argsArguments the server typed in the plugin. May be null (we'll get to that soon)
Program.cs — Main
public static Action<byte[]> _send;

static void Main(Action<byte[]> send, string[] args)
{
    _send = send;
    if (args == null || args.Length == 0)
    {
        ExecuteArg("default", "");
        return;
    }
    ParseArgs(args);
}
04 — pack & send

Pack & Send

Communication back to the client is done through the Pack class (from Stuff.dll). Fill key-value pairs, serialize with .Pacc(), and pass the resulting byte[] to _send.

Sending a message
Pack pack = new Pack();
pack.SetString("Packet",  "UserMessage");
pack.SetString("Message", "Hello from my plugin!");
pack.SetString("Status",  "Success");
_send(pack.Pacc());

Available Status values:

ValueLog entry
"Information"Sky blue entry — send information or current status
"Success"Green entry — operation completed successfully
"Warning"Yellow entry — non-critical notice
"Error"Red entry — something went wrong
05 — parsing arguments

Parsing Arguments

Arguments follow a -flag value convention. Iterate the args array, detect tokens starting with - as flag names, and accumulate subsequent tokens as the value. Use a StringBuilder for multi-word values.

ParseArgs helper
static void ParseArgs(string[] args)
{
    string currentArg = null;
    StringBuilder valueBuilder = new StringBuilder();

    for (int i = 0; i < args.Length; i++)
    {
        string arg = args[i];
        if (arg.StartsWith("-"))
        {
            if (currentArg != null)
                ExecuteArg(currentArg, valueBuilder.ToString());
            currentArg = arg.ToLower();
            valueBuilder.Clear();
        }
        else
        {
            if (valueBuilder.Length > 0) valueBuilder.Append(" ");
            valueBuilder.Append(arg);
        }
    }
    if (currentArg != null)
        ExecuteArg(currentArg, valueBuilder.ToString());
}
ℹ
Tip: Always use the "default" case in your switch. When invoked with no args, use it to print a usage hint.
06 — pack method reference

Pack Method Reference

MethodDescription
SetString(key, value)Store a string value under key
SetInt(key, value)Store an integer value under key
SetBytes(key, value)Store a byte array under key (e.g. file data)
Pacc()Serialize the Pack to byte[] — pass result to _send()
07 — full example

Full Example

Complete plugin. Responds to -msg <text> and prints a usage hint when called without arguments.

TestPlugin/Program.cs
using Stuff;
using System;
using System.Text;

namespace TestPlugin
{
    [PluginInfo("Example plugin for testing")]
    class Program
    {
        public static Action<byte[]> _send;

        static void Main(Action<byte[]> send, string[] args)
        {
            _send = send;
            if (args == null || args.Length == 0)
            {
                ExecuteArg("default", "");
                return;
            }
            ParseArgs(args);
        }

        static void ParseArgs(string[] args)
        {
            string currentArg = null;
            StringBuilder valueBuilder = new StringBuilder();
            for (int i = 0; i < args.Length; i++)
            {
                string arg = args[i];
                if (arg.StartsWith("-"))
                {
                    if (currentArg != null)
                        ExecuteArg(currentArg, valueBuilder.ToString());
                    currentArg = arg.ToLower();
                    valueBuilder.Clear();
                }
                else
                {
                    if (valueBuilder.Length > 0) valueBuilder.Append(" ");
                    valueBuilder.Append(arg);
                }
            }
            if (currentArg != null)
                ExecuteArg(currentArg, valueBuilder.ToString());
        }

        static void ExecuteArg(string arg, string value)
        {
            switch (arg)
            {
                case "-msg":
                    Pack pack = new Pack();
                    pack.SetString("Packet", "UserMessage");
                    pack.SetString("Message", "Your message was: " + value);
                    pack.SetString("Status", "Success");
                    _send(pack.Pacc());
                    break;
                default:
                    Pack pack2 = new Pack();
                    pack2.SetString("Packet", "UserMessage");
                    pack2.SetString("Message", "Try: -msg <text>");
                    pack2.SetString("Status", "Warning");
                    _send(pack2.Pacc());
                    break;
            }
        }
    }
}
08 — tips & tricks

Tips & Tricks

★

Always guard args for null

Raton may call your plugin with null when no input is given. Use default: as we said before

★

Store _send as static

The delegate is injected once in Main. Store it as a static field so all your methods can call it without passing it around.

★

Use Status semantically

Information, Success, Warning, and Error map to colored log entries. Don't mark everything as Success.

★

Keep plugins focused

One plugin = one purpose. Small, composable plugins are easier to debug and update. Or whatever...

★

Keep it safe

Be careful when executing code from other people, this may cause RCE attempts or client stealing.

© 2026 SillyCS. All rights reserved