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.
 
 
 

5.7 KiB

Custom Routines

TRBot also supports writing and running custom routines that run occasionally. Like custom commands, if you provide an empty ClassName and a path to a C# source file as the ValueStr of a routine with this class, it'll compile the file contents as code and execute it. This supports both absolute paths and files relative to the Data folder.

Custom routines are run every update loop, which is defined by the main_thread_sleep setting in the database. If the value of main_thread_sleep is 500 milliseconds for instance, then a custom routine will run every 500 milliseconds.

This tutorial will be using a routine called "printmsg" with a source file called "PrintMessageRoutine.cs".

Setting up a custom routine

First, we need to set up our custom routine 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 RoutineData table.
  2. Create a new record and fill out the following information:
  • Set the Name of the routine to something descriptive that mentions what it does. In our case, the name should be "printmsg".
  • Set the ClassName of the routine to be completely empty.
  • Set the Enabled value of the routine to 1 so it runs every update.
  • Set the ResetOnReload value of the routine to 0. This prevents the routine from being reset when bot data is reloaded with the ReloadCommand.
  • Set the ValueStr to the path of the file we're going to use, "PrintMessageRoutine.cs", without quotes.
  1. Write your changes to the database.

Writing a custom routine

The database currently has a "printmsg" routine that executes custom code from a file called "PrintMessageRoutine.cs" that's in our Data folder. Go ahead and create a text file named "PrintMessageRoutine.cs" in your Data folder. Make sure file extensions are fully visible in your operating system, otherwise the file might actually be named "PrintMessageRoutine.cs.txt".

Open up that file and input the following lines:

using System.Linq;
using Microsoft.EntityFrameworkCore;

public class PrintMessageRoutine : BaseRoutine
{
    public PrintMessageRoutine()
    {
        
    }
    
    public override void UpdateRoutine(in DateTime currentTimeUTC)
    {
        DataContainer.MessageHandler.QueueMessage($"{nameof(RoutineHandler)} is of type {RoutineHandler.GetType().FullName} | This routine's value is {ValueStr} | The current time is {currentTimeUTC}.");
        
        long maxCredits = 0;
        
        using (BotDBContext context = DatabaseManager.OpenContext())
        {
            var allUsers = context.Users.Include(e => e.Stats);
            maxCredits = allUsers.Max(u => u.Stats.Credits);
        }
        
        DataContainer.MessageHandler.QueueMessage($"The max number of credits in the database is {maxCredits}!");
    }
}

return new PrintMessageRoutine();

Save the file, load up TRBot, then wait for it to invoke the routine (hopefully your main_thread_sleep isn't too long!).

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

  1. "RoutineHandler is of type TRBot.Routines.BotRoutineHandler | This routine's value is PrintMessageRoutine.cs | The current time is t." ("t" being the current time)
  2. "The max number of credits in the database is x!" ("x" being the highest number of credits a user has in the database)

In basic terms, what this routine did was print a message with information, including the source file name and the current time. Finally, it loaded all users in the database with their stats and printed the highest credit count among them.

Like custom commands, if things didn't work out, 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 routines must return an instance of a class deriving from BaseRoutine.

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

Important considerations

  • Custom routines utilize C#'s scripting API, which is notorious for consuming large amounts of RAM. Too many custom routines can cause problems, so make sure to monitor your RAM usage if you have at least 5 custom routines.
  • Custom routines have access to the same fields and properties that other routines do.
  • 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.
  • Just like custom commands, custom routines 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 routine's source file.
  • Since custom routines directly utilize TRBot code, and TRBot directly executes the custom routines, 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 routines.