-
Notifications
You must be signed in to change notification settings - Fork 6
Writing Commands
This only applies if you're making a Rain World code mod and want to add commands to the console while it is installed.
Commands may be added at any time using DevConsole.GameConsole.RegisterCommand, passing in a DevConsole.Commands.ICommandHandler that defines when the command should run, what it should do when it runs, and what text should appear when running help. It may also implement DevConsole.Commands.IAutoCompletable to support autocomplete.
The main problem with inheriting from ICommandHandler is that it causes your mod to not load if DevConsole.dll is not found. An exception to be thrown when the mod loader tries to get all types in your assembly even if your command handler type would never be used. Instead, most commands should be created using DevConsole.Commands.CommandBuilder like so:
new CommandBuilder("hello_world") // Defines a command called "hello_world"
.Run(args => // Defines what happens when the command runs
{
GameConsole.WriteLine("Hello world!", Color.green); // Writes "Hello world!" to the console in green
})
.Register(); // Finalizes construction, adding the command to the consoleCommandBuilder has the following methods that change the behavior of the command:
-
Name(string)- Gives the command a name if one was not specified in the constructor -
Run(Action<string[]>)- Gives the command a delegate to run -
RunGame(Action<RainWorldGame, string[]>)- Gives the command a delegate to run and limits it to being called from in-game -
AutoComplete(Func<string[], IEnumerable<string>>)- Gives the command a delegate that determines the autocompletion options for an argument -
AutoComplete(string[][])- Gives the command a static list of autocompletion options for each argument -
Help(Func<string>)- Gives the command a delegate that determines its help text -
Help(string)- Gives the command static help text -
HideHelp()- Specifies that the command has no help text, since it defaults to the command's name -
Register()- Register the command, rendering the builder invalid
Using CommandBuilder.RunGame makes it a bit more convenient to have your command execute an in-game action.
new CommandBuilder("kill") // Defines a command called "kill"
.RunGame((game, args) => // Uses the RunGame method to specify that it may only run while in-game
{
foreach(var player in game.Players.Select(ply => ply.realizedObject as Player))
player?.Die();
})
.Register();If your command needs a position to function, using GameConsole.SpawnRoom and GameConsole.SpawnPos will allow the user to control where this is more effectively. By default these point to the first player's head, but may also point to the mouse position or camera position if the user runs target_pos.
Inheriting from ICommandHandler or using CommandBuilder in your mod's entry point will make it fail to load if DevConsole.dll is missing. To get around this, simply move all code that interacts with the Dev Console into its own method that is only called from within try blocks.
public void OnLoad()
{
try { RegisterCommands(); }
catch {}
}
private void RegisterCommands()
{
new CommandBuilder("my_command")
.Run(...)
.Register();
}If your command has subcommands or can predict a finite set of options for a parameter, it may be worthwhile to add autocomplete. Consider a command called print that writes text of the given color to the console with the syntax print [color] [alignment] [text]. It may be autocompleted like so:
new CommandBuilder("print") // Defines a command called "print"
.Run(...) // Run logic would go here
.AutoComplete(args => // Use the delegate version of autocomplete
{
// Argument 0: color
if (args.Length == 0) return new string[] { "black", "white", "red", "green", "blue" };
// Argument 1: alignment
if (args.Length == 1) return new string[] { "left", "center", "right" };
return null;
})
.Register();Since this command uses a fixed set of autocompletion arguments, another overload of CommandBuilder.AutoComplete may be used:
new CommandBuilder("print") // Defines a command called "print"
.Run(...) // Run logic would go here
.AutoComplete(new string[][] {
return new string[] { "black", "white", "red", "green", "blue" },
return new string[] { "left", "center", "right" }
})
.Register();This does the same, with the caveat that each argument may not change based on the one before it.