搬运自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 { //用户没有子权限 } } }