Pustalorc.RocketModExtended.Commands 1.0.1

.NET Framework 4.6.1
NuGet\Install-Package Pustalorc.RocketModExtended.Commands -Version 1.0.1
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.
dotnet add package Pustalorc.RocketModExtended.Commands --version 1.0.1
<PackageReference Include="Pustalorc.RocketModExtended.Commands" Version="1.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Pustalorc.RocketModExtended.Commands --version 1.0.1
#r "nuget: Pustalorc.RocketModExtended.Commands, 1.0.1"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install Pustalorc.RocketModExtended.Commands as a Cake Addin
#addin nuget:?package=Pustalorc.RocketModExtended.Commands&version=1.0.1

// Install Pustalorc.RocketModExtended.Commands as a Cake Tool
#tool nuget:?package=Pustalorc.RocketModExtended.Commands&version=1.0.1

RocketMod Commands Extended NuGet

Library to add abstracted command classes to make setups for commands under RocketMod (or LDM, as maintained by Nelson) easier.

Quick notes

Please be aware that all 3 of the abstracted classes inherit from eachother in the following order:
MultiThreadedRocketCommandRocketCommandWithTranslationsRocketCommandWithParsing
So inheriting from RocketCommandWithParsing will also inherit the multithread support and translations support.

If you wish to contribute to this repository, feel free by creating a PR to add/remove or change anything as need be.

References

This project includes the following NuGet packages in order to function as intended:
CommandLineParser v2.9.1
OpenMod.Unturned.Redist
OpenMod.UnityEngine.Redist

Usage

All you need for usage is to create a class and inherit from one of the 3 abstracted classes.
For example:

public sealed class PPlayersCommand : RocketCommandWithParsing<HelpOnly>
{
    protected override Dictionary<string, string> DefaultTranslations => new(StringComparer.OrdinalIgnoreCase)
    {
        { "command_exception", "Error during command execution. Command: {0}. Error: {1}. Full exception: {2}" },
        { "error_external_perm_provider", "This command cannot be used with an external permissions provider. Please run `/ap -p`, or make sure no other plugin overrides advanced permissions. External provider: {0}" },
        { "list_players", "{0} Players: {1}" },
        { "list_players_format", "{0} [{1}]" }
    };

    public override AllowedCaller AllowedCaller => AllowedCaller.Both;
    public override string Name => "p.players";
    public override string Help => "Lists all permission players on the server.";
    public override string Syntax => "[-h|--help]";

    public PPlayersCommand(bool multiThreaded, Dictionary<string, string> translations) : base(multiThreaded, translations, StringComparer.OrdinalIgnoreCase)
    {
    }

    public override async Task ExecuteAsync(IRocketPlayer caller, HelpOnly parsed)
    {
        switch (R.Permissions)
        {
            case IPermissionProviderController provider:
                var players = (await provider.GetPlayers())
                    .Select(k => Translate("list_players_format", k.LastSeenDisplayName, k.Key)).ToArray();

                SendTranslatedMessage(caller, "list_players", players.Length, string.Join(", ", players));
                break;
            default:
                SendTranslatedMessage(caller, "error_external_perm_provider", R.Permissions.GetType().FullName);
                break;
        }
    }
}

To explain a bit of what goes on here:

HelpOnly is a class used to only provide access to --help or -h when performing the command parsing within RocketCommandWithParsing<T>.
This HelpOnly class can be inherited from other classes, but you can also inherit from CommandParsing, which already enables --help or -h.
Note that you cannot use CommandParsing for RocketCommandWithParsing<T>.

DefaultTranslations is a dictionary for quick lookups on translations, and will be used by RocketCommandWithTranslations if the translation is not found from the loaded translations.

AllowedCaller, Name, Help, Syntax are all required properties by default from rocketmod, and will not be assumed from class names or anything.

The constructor requires a bool to determine if the command should be multithreaded. If you do not wish to provide an option in configuration to users for this, simply remove it from the consrtuctor and just pass true to the base constructor.
A Dictionary<string, string> is also needed to get the currently loaded translations, either from rocket or somewhere else.

Finally, the ExecuteAsync method passes the caller as usual, but also the parsed input, in this case HelpOnly which will always be false since RocketCommandWithParsing<T> automatically handles printing the help information.

Further usage

RocketCommandWithParsing<T>

If you wish, you can override the following method to replace or change the help message for the command:
protected virtual Task DisplayHelp(IRocketPlayer caller, ParserResult<T> parserResult)

You can also override the following method to change how parsing is performed or when the help message is raised:
public override async Task ExecuteAsync(IRocketPlayer caller, string[] command)

The constructor for RocketCommandWithParsing<T> has an additional and optional parameter Parser? parser = null which allows you to change the parser's settings instead of using a default.


RocketCommandWithTranslations

From the input loaded translations, only the required ones from DefaultTranslations are used, so if you find yourself seeing a translation key but no message, despite having it on the default translations of the plugin, you should consider adding it to the command instead.

You can reload translations if you ever need to with the following method:
public virtual void ReloadTranslations(Dictionary<string, string> translations)

You can override the following method in order to change how translations are retrieved and how the variables within the translation are parsed:
public virtual string Translate(string translationKey, params object?[] placeholder)
By default, this method will replace {i}, where i is a number, from within translations, but only as many i's as count in the placeholder input, so having a translation with {0} said {1} {2} will not throw an error if you only pass to the placeholder 2 elements

You can also override the following method to change how exceptions are logged when the command executes, as they are captured due to the default multithreaded support:
protected override void LogException(IRocketPlayer caller, Exception exception)
By default this method will use the translation key command_exception, so you should include one always in your command's default translations.


MultiThreadedRocketCommand

You can change the multithreaded setting with the following method:
public void ReloadMultiThreaded(bool multiThreaded)
This is useful if you are using a configuration setting for this option and the configuration gets changed and reloaded.

Like with RocketCommandWithTranslations, you can override the following method in order to change how exceptions get logged.
protected virtual void LogException(IRocketPlayer caller, Exception exception)
Since the multithreaded class does not include translations by default, this class will log a built in default message in english that will mention the command name that failed, the exception message, and the full exception.

You can also override the following method to change how multithreading is done, or if it even should be done at all: public virtual void Execute(IRocketPlayer caller, string[] command)

Product Versions
.NET Framework net461 net462 net463 net47 net471 net472 net48
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

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
1.0.1 82 7/27/2022
1.0.0 102 7/9/2022
1.0.0-pre 59 6/22/2022

Fixed an issue with the input dictionary not being soft copied, resulting in each command modifying loaded translations for eachother.