baer1.ChatCommandAPI 0.1.2

There is a newer version of this package available.
See the version list below for details.
dotnet add package baer1.ChatCommandAPI --version 0.1.2
                    
NuGet\Install-Package baer1.ChatCommandAPI -Version 0.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="baer1.ChatCommandAPI" Version="0.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="baer1.ChatCommandAPI" Version="0.1.2" />
                    
Directory.Packages.props
<PackageReference Include="baer1.ChatCommandAPI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add baer1.ChatCommandAPI --version 0.1.2
                    
#r "nuget: baer1.ChatCommandAPI, 0.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=baer1.ChatCommandAPI&version=0.1.2
                    
Install baer1.ChatCommandAPI as a Cake Addin
#tool nuget:?package=baer1.ChatCommandAPI&version=0.1.2
                    
Install baer1.ChatCommandAPI as a Cake Tool

This mod is unfinished.

There may be major breaking changes before the first full release.

If you encounter any issues while playing or creating a mod with this API, please report them on GitHub.

This mod is open-source, you can contribute to it by opening a pull request

Getting started

1. Include API in your project

Simply run dotnet add package baer1.ChatCommandAPI or add the following line to your csproj file:

<PackageReference Include="baer1.ChatCommandAPI" Version="0.1.*"/>

Additionally, you should reference this mod in both your main plugin class and your manifest.json (replace <VERSION> with the actual version you are using):

...
[BepInPlugin(MyPluginInfo.PLUGIN_GUID, MyPluginInfo.PLUGIN_NAME, MyPluginInfo.PLUGIN_VERSION)]
[BepInDependency("baer1.ChatCommandAPI", BepInDependency.DependencyFlags.HardDependency)]
public class ExampleMod : BaseUnityPlugin
...
...
"dependencies": [
"BepInEx-BepInExPack-5.4.2100",
"baer1-ChatCommandAPI-<VERSION>",
...
]
...

2. Create Command Subclass

Simply create a non-static class that inherits the ChatCommandAPI.Command class. The Invoke method contains the logic that will be run.

The default command name is the class name you assign to it, ExampleCommand in the example below. You can run this command through the in-game chat. (See below for changing it)

This mod is case-insensitive (/eXaMpLeCoMmAnD is valid)

Example:

using System.Collections.Generic;
using ChatCommandAPI;

namespace ExampleMod;

public class ExampleCommand : Command
{
    public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
    {
        error = null!;
        // Put your code here
        return true;
    }
}

3. Instantiate the Subclass once

namespace ExampleMod;

public class ChatCommandAPI : BaseUnityPlugin
{
    private void Awake()
    {
        _ = new ExampleCommand();
    }
}

4. Done!

You can now use the command /examplecommand in-game to run the function defined in Step 2

Advanced usage

Customizing the command

You can overwrite several properties of the Command class to customize your command:

using System.Collections.Generic;
using ChatCommandAPI;

namespace ExampleMod;

public class ExampleCommand : Command
{
    public override string Name => "Example"; // Command name (default: Class name)
    public override string[] Commands =>
        ["MyCommand", Name, "ExampleCommand", "Command", "HelloWorld"]; // Aliases (first entry is displayed on help, default: Name.ToLower())
    public override string Description => "Prints Hello World [amount] times"; // Short description of this command
    public override string[] Syntax => ["", "[amount]"]; // All valid syntaxes for this command (only for help, not validated)
    public override bool Hidden => false; // Whether to hide this command from the help list (useful for debugging, default: false)

    public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
    {
        error = "Invalid argument"; // Set error for return value false
        ushort amount = 1;
        if (args.Length > 0)
            if (!ushort.TryParse(args[0], out amount))
                return false; // Return value false: reports error to user
        while (amount > 0)
        {
            ChatCommandAPI.ChatCommandAPI.Instance.Print("Hello, World!");
            amount--;
        }
        return true; // Return value true: success, doesn't do anything
    }
}

The above results in the following being displayed on the help list:

Example - Prints Hello World [amount] times
/MyCommand
/MyCommand [amount]

Server commands

Server commands are commands that anyone on the server can use, as long as the host has them installed.

They are very similar to the client commands.

Example:

using System.Collections.Generic;
using GameNetcodeStuff;
using Unity.Netcode;

namespace ChatCommandAPI.BuiltinCommands;

public class ServerPing : ServerCommand
{
    public override string Name => "Ping"; // Command name
    public override string Description => "Displays your latency to the server"; // Command description (for !help)

    public override bool Invoke(
        ref PlayerControllerB? caller, // Player that sent the command (can be spoofed, this may be fixed in the future)
        string[] args,
        Dictionary<string, string> kwargs,
        out string error
    )
    {
        error = "caller is null"; // error message is not reported to anyone, but it is logged
        if (caller == null) // We need a player to run this command to get their ping
            return false;

        ChatCommandAPI.Print(
            caller, // Only prints text to this player
            $"Latency: {Ping(caller)}ms"
        );
        return true;
    }

    // returns ping of player
    private static ulong Ping(PlayerControllerB player) =>
        NetworkManager.Singleton.NetworkConfig.NetworkTransport.GetCurrentRtt(
            player.actualClientId
        );
}

Using ToggleCommand

If you are creating a command that is supposed to act as a toggle (on or off), you can use the ToggleCommand class to make this easier.

You can override the Value property to access it externally or in harmony patches:

using GameNetcodeStuff;
using HarmonyLib;
using ChatCommandAPI;

namespace ExampleMod;

public class ExampleToggleCommand : ToggleCommand
{
    public override string Name => "BlockJump"; // Command name
    public override string ToggleDescription => "Blocks jump inputs"; // Use ToggleDescription instead of Description
    public override string EnabledString => "blocked"; // String to use when Value=false
    public override string DisabledString => "unblocked"; // String to use when Value=true

    public override void PrintValue() => ChatCommandAPI.Print($"Jump inputs {ValueString}"); // Called after value is updated, for user feedback

    public override bool Value // Redirect reads and writes to static property
    {
        get => BlockJump;
        set => BlockJump = value;
    }
    public static bool BlockJump { get; internal set; } // Static property for external access

    [HarmonyPatch(typeof(PlayerControllerB), nameof(PlayerControllerB.Jump_performed))]
    internal class Patch
    {
        private static bool Prefix() => !BlockJump; // Block jump
    }
}

Player arguments

If you want to allow a player name as an argument, you should use the Utils.GetPlayer function:

using System.Collections.Generic;
using ChatCommandAPI;
using GameNetcodeStuff;

namespace ExampleMod;

public class ExamplePlayerCommand : Command
{
    public override string Name => "IsPlayerDead"; // Command name
    public override string Description => "Shows if a player is dead"; // Command description
    public override string[] Syntax => ["[player]"];

    public override bool Invoke(string[] args, Dictionary<string, string> kwargs, out string error)
    {
        error = null!; // Don't set error message like "Player not found", this error is reported by the GetPlayer function automatically
        PlayerControllerB player = GameNetworkManager.Instance.localPlayerController;
        if (args.Length > 0)
            if (!Utils.GetPlayer(args[0]))
                return false; // Report failure, no error message, prevents further execution
        ChatCommandAPI.ChatCommandAPI.Print(
            player.isPlayerDead
                ? $"Player {player.playerUsername} is dead."
                : $"Player {player.playerUsername} is not dead."
        );
        return true; // Report success
    }
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.4 92 5/31/2025
0.1.3 132 5/28/2025
0.1.2 136 5/26/2025
0.1.1 134 5/26/2025
0.1.0 131 5/26/2025
0.0.5 227 5/13/2025
0.0.4 208 5/12/2025
0.0.3 80 5/9/2025
0.0.2 91 5/9/2025