• 注册
  • 技术交流 技术交流 关注:8 内容:20

    [OpenMod]命令文档

  • 查看作者
  • 打赏作者
  • 当前位置: 未转变者中文社区 > 技术交流 > 正文
    大版主
    Lv.15

    搬运自OpenMod官网,经过翻译,可能有些不足,欢迎指正!原文链接

    命令

    若要创建命令,请创建从以下对象之一继承的类:

      Command(用于通用插件)

      UnityEngineCommand(用于UnityEngine插件)

      UnturnedCommand(用于Unturned的插件)

    在本例中,我们将生成一个通用命令,可在任何游戏或平台上运行:

    public class CommandAwesome : Command
    {
        public CommandAwesome(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    }

    添加元数据以描述命令:

    [Command("awesome")] // 命令的主要名称。通常,它被定义为小写。
    [CommandAlias("awsm")] // 添加“awsm”作为别名。
    [CommandAlias("aw")] // 添加“aw”作为别名。
    [CommandDescription("My awesome command")] // 描述。尽量简短。
    public class CommandAwesome : Command
    {
        public CommandAwesome(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    }

    实现OnExecuteAsync:

    [Command("awesome")] 
    [CommandAlias("awsm")]
    [CommandAlias("aw")]
    [CommandDescription("My awesome command")]
    public class CommandAwesome : Command
    {
        public CommandAwesome(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    
        // 如果从UnityEngineCommand或UnturnedCommand派生,请使用UniTask而不是Task
        public async Task OnExecuteAsync() 
        {
            await PrintAsync("OpenMod is awesome!");
        }
    }

    警告

    避免像上面的例子那样对消息进行硬编码。相反,使用本地化,这样用户就可以定制和翻译消息。

    参数

    大多数命令通常需要参数。命令context为此提供参数属性:

    public async Task OnExecuteAsync()
    {
        // 假设我们希望命令的调用方式如下:/awesome <player> <amount>
        // 参数从0开始,因此<player>索引为0,<amount>索引为1。
        var player = await Context.Parameters.GetAsync<string>(0);
        var amount = await Context.Parameters.GetAsync<int>(1);
        await PrintAsync($"{player} is {amount}x awesome!");
    }

    之后,您需要描述用户如何使用该命令。将语法元数据添加到命令类:

    //...
    [CommandSyntax("<player> [amount]")] // 描述语法/usage。使用<>作为必需参数,[]作为可选参数。
    public class CommandAwesome : Command
    //...

    限制命令使用者

    如果您没有开发通用插件,您可能需要限制谁可以执行命令。

    [CommandActor(Type)]属性允许您指定此类限制。

    例如,如果要将命令的使用限制为UnturnedUser和ConsoleActor,可以添加以下内容:

    //...
    [CommandActor(typeof(UnturnedUser))]
    [CommandActor(typeof(ConsoleActor))]
    public class CommandAwesome : Command
    //...

    警告

    默认情况下,任何用户类型都可以执行您的命令。插件可以动态地添加新用户,比如DiscordUser、PluginUser、RconUser等。用一种适合所有用户的方式编写命令。如果这是不可能的(例如,一个/god命令需要UnturnedUser),像上面提到的那样限制允许的使用者。

    小心 

    不要手动检查是否允许使用者执行命令(例如,if(!(actor is UnturnedUser)))。对于此类限制,请始终使用[CommandActor(Type)]。它将自动对无法执行命令的参与者隐藏命令,并给出一致的错误消息。

    例外情况

    UserFriendlyException派生的异常由OpenMod自动捕获,并以易于掌握的方式向用户显示消息。

    这些内置的方便非专业用户的例子:

       NotEnoughPermissionException,如果用户没有足够的权限执行操作,则可以引发。

       CommandErrorUsageException,可以在错误的命令使用时引发。根据命令语法显示正确用法。

       CommandIndexOutOfRangeException,由自动引发参数。获取如果给定的索引大于参数长度。

       CommandParameterParseException,由自动引发参数。获取如果无法将参数解析为预期类型。

       CommandNotFoundException,未找到命令时自动引发。

    public async Task OnExecuteAsync()
    {
        var player = await Context.Parameters.GetAsync<string>(0);
        var amount = await Context.Parameters.GetAsync<int>(1);
    
        if(amount < 1) 
        {
            throw new UserFriendlyException("Amount cannot be negative!");
        }
    
        await PrintAsync($"{player} is {amount}x awesome!");
    }

    命令权限

    出于设计和一致性原因,您不能手动定义命令权限。OpenMod将自动为命令分配权限。您可以使用help <yourcommand>命令来确定命令的基本权限。

    假设您想要限制awesome命令,如果数量超过10。你应该这样做:

    public async Task OnExecuteAsync()
    {
        var player = await Context.Parameters.GetAsync<string>(0);
        var amount = await Context.Parameters.GetAsync<int>(1);
    
        if(amount > 10 && await CheckPermissionAsync("MoreThan10") != PermissionGrantResult.Grant) 
        {
            throw new NotEnoughPermissionException(this, "MoreThan10"); // 向用户显示错误消息
        }
    
        await PrintAsync($"{player} is {amount}x awesome!");
    }

    小心

    不要手动检查常规命令使用权限。OpenMod自动定义命令的权限。一个错误的例子:

    public async Task OnExecuteAsync()
    {
        if (!await CheckPermissionAsync("MyCommand")) 
        {
           //throw ... 或者更糟的 await PrintAsync(...) 
        }
    }

    小心

    不要手动发送丢失的权限消息。一直抛出NotEnoughPermissionException异常。

    添加子命令

    您可以使用[CommandParent]属性将子命令添加到命令中。这允许OpenMod发现您的子命令,并提供额外的帮助和选项卡自动完成。

    当用户键入“/awesome more”时,将执行以下命令。这个CommandAwesome.OnExecuteAsync命令方法在这种情况下将不执行。

    [Command("more")] 
    [CommandDescription("My more awesome command")]
    [CommandParent(typeof(CommandAwesome))] // set "awesome" as parent.
    public class CommandAwesomeMore : Command
    {
        public CommandAwesomeMore(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    
        public async Task OnExecuteAsync()
        {
            // 注:参数不包括"more"。
            // 如果您键入"/awesome more a",Context.Parameters[0]将等于"a". 
            await PrintAsync("You are even more awesome!");
        }
    }

    小心

    不要自己处理子命令(例如,if(Context.Parameters[0] == “add”))。手动处理子命令时,OpenMod无法发现子命令并提供其他帮助、权限或选项卡自动完成。

    添加子权限

    您可以为命令添加子权限,它们需要使用[RegisterCommandPermission(“child.permission”)]来检查用户是否有需要调用await CheckPermissionAsync(“child.permission”)并检查结果。

    例子:

    [Command("more")] 
    [RegisterCommandPermission("child.permission", Description = "My awesome permission description", DefaultGrant = PermissionGrantResult.Default)]
    //Description and DefaultGrant are optional
    
    public class CommandAwesomeMore : Command
    {
        public CommandAwesomeMore(IServiceProvider serviceProvider) : base(serviceProvider)
        {
        }
    
        public async Task OnExecuteAsync()
        {
            //MyPlugin:AwesomeMore.child.permission
            if (await CheckPermissionAsync("child.permission") == PermissionGrantResult.Grant)
            {
                //用户具有子权限
            }
            else
            {
                //用户没有子权限
            }
        }
    }

    Lv.1
    置顶
    […] 有关更多信息,请访问命令文档。 […]
    回复
    Lv.1
    […] 你应该在加载插件时注册你的权限。如果有命令相关的权限,则有更好的方法来注册它们,请检查命令文档。 […]
    回复

    请登录之后再进行评论

    登录
  • 发布内容
  • 任务中心
  • 实时动态
  • 偏好设置
  • 帖子间隔 侧栏位置: