Powerful software for playing games through text, supporting remote connectivity through services such as Twitch.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

10 KiB

Custom Commands

TRBot supports writing and running custom commands. If you provide an empty ClassName and a path to a C# source file as the ValueStr of a command, it'll read the file contents as code and compile it to be invoked upon receiving the command. The ValueStr supports both absolute paths and files relative to the Data folder.

This tutorial will be using a command called "testcmd" with a source file called "TestCmd.cs".

Setting up the custom command

First we have to set up the custom command in the database. If you don't know how to view the database, please read managing data.

  1. Open the database and navigate to the CommandData table.
  2. Create a new record and fill out the following information:
  • Set the Name of the command to be something descriptive that mentions what it does. In our case, the name should be "testcmd".
  • Set the ClassName of the command to be completely empty.
  • Set the Level value of the command to be the access level you want. For this tutorial, we want this command accessible to everyone, so set it to 0 (User level).
  • Set the Enabled value of the command to be 1 so we can actually use it.
  • Set the DisplayInList value of the command to 1. We can still use it if it's 0, but unless you don't want users seeing it in the help list for ListCmdsCommand, set it to 1.
  • Set the ValueStr to the path of the file we're going to use, "TestCmd.cs", without quotes.
  1. Write your changes to the database.

Writing a custom command

Right now the database has a "testcmd" command that will execute custom code from a file called "TestCmd.cs" that's in our Data folder. Go ahead and create a text file named "TestCmd.cs" in your Data folder. Make sure file extensions are fully visible in your operating system, otherwise the file might actually be named "TestCmd.cs.txt".

Open up that file and input the following lines:

using System;
using TRBot.Commands;

public class TestCmd : BaseCommand
{
    public TestCmd()
    {
        
    }

    public override void ExecuteCommand(EvtChatCommandArgs args)
    {
        QueueMessage("This is a test cmd!");
        
        using (BotDBContext context = DatabaseManager.OpenContext())
        {
            User user = DataHelper.GetUserNoOpen("terminaluser", context);
            
            QueueMessage($"{user.Name} has {user.Stats.Credits} credits!!!!!!!");
        }
        
        QueueMessage($"Cmd Level: {Level} | Enabled: {Enabled}");

        QueueMessage($"Evt chat command args: {args.Command.ArgumentsAsString}");
    }
}

return new TestCmd();

Save the file, load up TRBot (or hard reload with "!reload hard" if it's already running), then type "!testcmd a b cd" to invoke the command.

If all went well, you should see the following messages in order:

  1. "This is a test cmd!"
  2. "terminaluser has x credits!!!!!!!" ("x" being the number of credits for "terminaluser")
  3. "Cmd Level: 0 | Enabled: True"
  4. "Evt chat command args: a b cd"

In basic terms, what this command did was print a message, load a user object from the database and print their credit count. Then, it printed data about the command itself and finally printed the arguments given to the command.

If things didn't go so well, you should see an error message in your console. If this happens, double-check your database settings and make sure the code doesn't have any syntax errors.

Return Value

All custom commands must return an instance of a class deriving from BaseCommand.

The example above achieves this by defining a new TestCmd class deriving from BaseCommand, then returning a new instance of TestCmd after the class definition. This is necessary since the CommandHandler that manages the in-memory command instances will then be able to initialize and execute your custom code just like any other command. It can't do this if it doesn't know which command to use!

Important things to note

  • Custom commands utilize C#'s scripting API, which is notorious for consuming large amounts of RAM. Too many custom commands can cause problems, so make sure to monitor your RAM usage if you have at least 5 custom commands.
  • Custom commands have access to the same fields and properties that other commands do.
  • Use QueueMessage over Console.WriteLine to send messages through the current client service. On top of sending the messages to the correct destination, QueueMessage also respects the rate-limiting settings for TRBot.
  • Custom commands have most other TRBot projects and several common namespaces imported (such as System). Anything else will need their full type names, or you will need to explicitly include the namespace. For example, StringBuilder needs to be referenced as System.Text.StringBuilder, but if you want just StringBuilder, you will need to add using System.Text; at the top of your custom command's source file.
  • Since custom commands directly utilize TRBot code, and TRBot directly executes the custom commands, custom commands are subject to the same licensing terms as TRBot itself. Keep this in mind if you intend to include any sensitive data in your custom commands.

Legacy Tutorial

This tutorial covers the legacy custom commands invoked through the ExecFromFileCommand. This method is deprecated and will be removed in a future release. It's recommended to convert your existing custom commands to the new system and use the new system for new custom commands going forwards.

Why will the legacy method be removed? In short, it uses more memory, does not easily allow for persistence in the custom code (Ex. defining an array will allocate that array each time the code is run), and doesn't treat custom commands like first-class citizens, unlike the new method.

There are some important things to note with legacy custom commands that will be mentioned later.

Setting up a custom command (LEGACY)

First, we need to set up our custom command in the database. If you don't know how to view the database, please read managing data.

  1. Open the database and navigate to the CommandData table.
  2. Create a new record and fill out the following information:
  • Set the Name of the command to be something descriptive that mentions what it does. In our case, the name should be "testcmd".
  • Set the ClassName of the command to be TRBot.Commands.ExecFromFileCommand.
  • Set the Level value of the command to be the access level you want. For this tutorial, we will have this accessible to everyone, so set it to 0 (User level).
  • Set the Enabled value of the command to be 1 so we can actually use it.
  • Set the DisplayInList value of the command to 1. We can still use it if it's 0, but unless you don't want users seeing it in the help list for ListCmdsCommand, set it to 1.
  • Set the ValueStr to the path of the file we're going to use, "TestCmd.cs", without quotes.
  1. Write your changes to the database.

Writing a custom command (LEGACY)

Right now the database has a "testcmd" command that will execute custom code from a file called "TestCmd.cs" that's in our Data folder. Go ahead and create a text file named "TestCmd.cs" in your Data folder. Make sure file extensions are fully visible in your operating system, otherwise the file might actually be named "TestCmd.cs.txt".

Open up that file and input the following lines:

DataContainer.MessageHandler.QueueMessage("This is a test cmd!");

using (BotDBContext context = DatabaseManager.OpenContext())
{
    User user = DataHelper.GetUserNoOpen("terminaluser", context);
    
    DataContainer.MessageHandler.QueueMessage($"{user.Name} has {user.Stats.Credits} credits!!!!!!!");
}

DataContainer.MessageHandler.QueueMessage($"Cmd Level: {ThisCmd.Level} | Enabled: {ThisCmd.Enabled}");

DataContainer.MessageHandler.QueueMessage($"Evt chat command args: {Args.Command.ArgumentsAsString}");

Save the file, load up TRBot (or hard reload with "!reload hard" if it's already running), then type "!testcmd a b cd" to invoke the command.

If all went well, you should see the following messages in order:

  1. "This is a test cmd!"
  2. "terminaluser has x credits!!!!!!!" ("x" being the number of credits for "terminaluser")
  3. "Cmd Level: 0 | Enabled: True"
  4. "Evt chat command args: a b cd"

In basic terms, what this command did was print a message, load a user object from the database and print their credit count. Then, it printed data about the command itself and finally printed the arguments given to the command.

If things didn't go so well, you should see a descriptive error message in your console. The nice thing about custom commands is you can change their source code while TRBot is running, and those changes will be applied immediately!

Important things to note (LEGACY)

  • Custom commands have access to the following global fields:
  • ThisCmd - The command instance being executed. From here you can access fields such as Level, Enabled, and more.
  • CmdHandler - The command handler that all commands have access to.
  • DataContainer - The data container instance all commands have access to. From here you can access the message handler, virtual controller manager, and more.
  • RoutineHandler - The bot routine handler.
  • Args - The EvtChatCommandArgs containing data about the user who ran the command, the supplied arguments, and more.
  • Use DataContainer.MessageHandler.QueueMessage over Console.WriteLine to send messages through the current client service. On top of sending the messages to the correct destination, QueueMessage also respects the rate-limiting settings for TRBot.
  • Custom commands have most other TRBot projects and several common namespaces imported (such as System). Anything else will need their full type names, or you will need to explicitly include the namespace. For example, StringBuilder needs to be referenced as System.Text.StringBuilder, but if you want just StringBuilder, you will need to add using System.Text; at the top of your custom command's source file.
  • While custom commands have access to most of TRBot, it may not be possible to add additional libraries or do much beyond what TRBot is already capable of.
  • Since custom commands are directly utilizing TRBot code, and TRBot is directly executing the custom commands, they are subject to the same licensing terms as TRBot itself. Keep this in mind if you intend to include any sensitive data in your custom commands.