Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switching game modes now requires OP. Provide user feedback on command failure. #278

Merged
merged 1 commit into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions Obsidian.API/_Attributes/RequirePermissionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public sealed class RequirePermissionAttribute : BaseExecutionCheckAttribute
{
private string[] permissions;
private PermissionCheckType checkType;
private bool op;
private readonly string[] _permissions;
private readonly PermissionCheckType _checkType;
private readonly bool _op;

public PermissionCheckType CheckType => _checkType;
public string[] RequiredPermissions => _permissions;

public RequirePermissionAttribute(PermissionCheckType checkType = PermissionCheckType.All, bool op = true, params string[] permissions)
{
this.permissions = permissions;
this.checkType = checkType;
this.op = op;
_permissions = permissions;
_checkType = checkType;
_op = op;
}

public override Task<bool> RunChecksAsync(CommandContext context)
Expand All @@ -20,11 +23,11 @@ public override Task<bool> RunChecksAsync(CommandContext context)
return Task.FromResult(true);
if (context.Player == null)
return Task.FromResult(false);
if (this.op && context.Player.IsOperator)
if (_op && context.Player.IsOperator)
return Task.FromResult(true);

if (this.permissions.Length > 0)
return Task.FromResult(checkType == PermissionCheckType.All ? context.Player.HasAllPermissions(permissions) : context.Player.HasAnyPermission(permissions));
if (_permissions.Length > 0)
return Task.FromResult(_checkType == PermissionCheckType.All ? context.Player.HasAllPermissions(_permissions) : context.Player.HasAnyPermission(_permissions));

return Task.FromResult(false);
}
Expand Down
25 changes: 22 additions & 3 deletions Obsidian/Commands/Framework/CommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,33 @@ public async Task ProcessCommand(CommandContext ctx)
// if string is "command-qualified" we'll try to execute it.
string[] command = CommandParser.SplitQualifiedString(qualified); // first, parse the command

await ExecuteCommand(command, ctx);
try
{
await ExecuteCommand(command, ctx);
}
catch (CommandExecutionCheckException ex)
{
await ProvideFeedbackToSender(ctx, ex);
}
}
}

private static async Task ProvideFeedbackToSender(CommandContext ctx, CommandExecutionCheckException ex)
{
switch (ex)
{
case NoPermissionException:
await ctx.Sender.SendMessageAsync(ChatMessage.Simple("You are not allowed to execute this command", ChatColor.Red));
break;
default:
await ctx.Sender.SendMessageAsync(ChatMessage.Simple(ex.Message, ChatColor.Red));
break;
}
}

private async Task ExecuteCommand(string[] command, CommandContext ctx)
{
Command cmd = null;
Command? cmd = default;
var args = command;

// Search for correct Command class in this._commands.
Expand All @@ -201,7 +221,6 @@ private async Task ExecuteCommand(string[] command, CommandContext ctx)
if (cmd is not null)
{
ctx.Plugin = cmd.Plugin?.Plugin;

await cmd.ExecuteAsync(ctx, args);
}
else
Expand Down
7 changes: 6 additions & 1 deletion Obsidian/Commands/Framework/Entities/Command.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Obsidian.Commands.Framework.Exceptions;
using Obsidian.Plugins;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Obsidian.Commands.Framework.Entities;

Expand Down Expand Up @@ -157,7 +158,11 @@ public async Task ExecuteAsync(CommandContext context, string[] args)
{
// A check failed.
// TODO: Tell user what arg failed?
throw new CommandExecutionCheckException($"One or more execution checks failed.");
throw c switch
{
RequirePermissionAttribute r => new NoPermissionException(r.RequiredPermissions, r.CheckType),
_ => new CommandExecutionCheckException($"One or more execution checks failed."),
};
}
}

Expand Down
19 changes: 19 additions & 0 deletions Obsidian/Commands/Framework/Exceptions/NoPermissionException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Obsidian.Commands.Framework.Exceptions;

/// <summary>
/// Exception indicating that a command can not be executed by a certain CommandExecutor due to missing required permissions.
/// </summary>
internal class NoPermissionException : CommandExecutionCheckException
{
public PermissionCheckType CheckType { get; }
public string[] RequiredPermissions { get; }


public NoPermissionException(string[] requiredPermsissions, PermissionCheckType checkType) : base("CommandSender does not have the required permissions.")
{
RequiredPermissions = requiredPermsissions;
CheckType = checkType;
}

}

1 change: 1 addition & 0 deletions Obsidian/Commands/MainCommandModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ public Task UptimeAsync(CommandContext ctx)
[Command("gamemode")]
[CommandInfo("Change your gamemode.", "/gamemode <survival/creative/adventure/spectator>")]
[IssuerScope(CommandIssuers.Client)]
[RequirePermission(op: true, permissions: "obsidian.gamemode")]
public async Task GamemodeAsync(CommandContext ctx, string gamemode)
{
var player = ctx.Player;
Expand Down