Skip to content

Commit 442a6dd

Browse files
committed
Added permissions to command overloads (+ allowed multiple overloads on a singular command method)
1 parent 2c9daa0 commit 442a6dd

4 files changed

Lines changed: 73 additions & 49 deletions

File tree

LabExtended/Commands/Attributes/CommandOverloadAttribute.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/// <summary>
44
/// Marks a method inside a <see cref="CommandBase"/> subtype as a command overload.
55
/// </summary>
6-
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
6+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
77
public class CommandOverloadAttribute : Attribute
88
{
99
internal readonly bool isDefaultOverload = false;
@@ -18,25 +18,32 @@ public class CommandOverloadAttribute : Attribute
1818
/// </summary>
1919
public string? Description { get; }
2020

21+
/// <summary>
22+
/// Gets the overload's required permission node.
23+
/// </summary>
24+
public string? Permission { get; }
25+
2126
/// <summary>
2227
/// Creates a new <see cref="CommandOverloadAttribute"/> instance.
2328
/// </summary>
24-
public CommandOverloadAttribute(string? description = null)
29+
public CommandOverloadAttribute(string description = "No description", string? permission = null)
2530
{
2631
isDefaultOverload = true;
27-
28-
if (description != null)
29-
Description = description;
32+
33+
Description = description;
34+
Permission = permission;
3035
}
3136

3237
/// <summary>
3338
/// Creates a new <see cref="CommandOverloadAttribute"/> instance.
3439
/// </summary>
3540
/// <param name="name">Name of the overload.</param>
3641
/// <param name="description">Description of the overload.</param>
37-
public CommandOverloadAttribute(string name, string description = "No description")
42+
/// <param name="permission">Sets the permission required to invoke the overload.</param>
43+
public CommandOverloadAttribute(string name, string description = "No description", string? permission = null)
3844
{
3945
Name = name;
4046
Description = description;
47+
Permission = permission;
4148
}
4249
}

LabExtended/Commands/CommandManager.cs

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
using LabApi.Events.Arguments.ServerEvents;
44
using LabApi.Events.Handlers;
55

6-
using LabApi.Features.Enums;
76
using LabApi.Features.Permissions;
87

8+
using LabExtended.Commands.Runners;
99
using LabExtended.Commands.Utilities;
1010
using LabExtended.Commands.Attributes;
1111
using LabExtended.Commands.Interfaces;
@@ -14,16 +14,11 @@
1414

1515
using LabExtended.API;
1616
using LabExtended.Core;
17-
using LabExtended.Attributes;
18-
using LabExtended.Commands.Runners;
1917
using LabExtended.Extensions;
20-
using LabExtended.Utilities.Unity;
21-
22-
using MEC;
2318

2419
using NorthwoodLib.Pools;
25-
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
2620

21+
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
2722
#pragma warning disable CS8604 // Possible null reference argument.
2823
#pragma warning disable CS8601 // Possible null reference assignment.
2924
#pragma warning disable CS8602 // Dereference of a possibly null reference.
@@ -108,47 +103,50 @@ public static List<CommandData> RegisterCommands(this Assembly assembly)
108103
{
109104
if (method.IsStatic)
110105
continue;
111-
112-
if (!method.HasAttribute<CommandOverloadAttribute>(out var commandOverloadAttribute))
113-
continue;
114-
115-
if (method.ReturnType != typeof(void) && method.ReturnType != typeof(IEnumerator<float>) && method.ReturnType != typeof(Task))
116-
{
117-
ApiLog.Warn("Command Manager", $"Method &3{method.GetMemberName()}&r cannot be used as an overload " +
118-
$"because it's return type is not supported (&1{method.ReturnType.FullName}&r). " +
119-
$"Command method's should return only &1void&r, &1IEnumerator<float>&r coroutine or a &1Task&r.");
120-
continue;
121-
}
122-
123-
var overload = new CommandOverload(method);
124-
125-
overload.Name = commandOverloadAttribute.Name;
126-
overload.Description = commandOverloadAttribute.Description;
127106

128-
if (commandOverloadAttribute.isDefaultOverload)
107+
foreach (var commandOverloadAttribute in method.GetCustomAttributes<CommandOverloadAttribute>(false))
129108
{
130-
if (instance.DefaultOverload != null)
109+
if (method.ReturnType != typeof(void)
110+
&& method.ReturnType != typeof(IEnumerator<float>)
111+
&& method.ReturnType != typeof(Task))
131112
{
132-
ApiLog.Error("Command Manager", $"Method &1{method.GetMemberName()}&r in command &1{instance.Name}&r " +
133-
$"was specified as the default overload, but the command already has one " +
134-
$"(&3{instance.DefaultOverload.Target.GetMemberName()}&r)");
135-
113+
ApiLog.Warn("Command Manager", $"Method &3{method.GetMemberName()}&r cannot be used as an overload " +
114+
$"because it's return type is not supported (&1{method.ReturnType.FullName}&r). " +
115+
$"Command method's should return only &1void&r, &1IEnumerator<float>&r coroutine or a &1Task&r.");
136116
continue;
137117
}
138-
139-
instance.DefaultOverload = overload;
140-
}
141-
else
142-
{
143-
if (instance.Overloads.ContainsKey(commandOverloadAttribute.Name))
118+
119+
var overload = new CommandOverload(method);
120+
121+
overload.Name = commandOverloadAttribute.Name;
122+
overload.Permission = commandOverloadAttribute.Permission;
123+
overload.Description = commandOverloadAttribute.Description;
124+
125+
if (commandOverloadAttribute.isDefaultOverload)
144126
{
145-
ApiLog.Error("Command Manager", $"Method &1{method.GetMemberName()}&r in command &1{instance.Name}&r" +
146-
$"cannot be added as an overload because an overload with the same name already exists.");
147-
148-
continue;
127+
if (instance.DefaultOverload != null)
128+
{
129+
ApiLog.Error("Command Manager", $"Method &1{method.GetMemberName()}&r in command &1{instance.Name}&r " +
130+
$"was specified as the default overload, but the command already has one " +
131+
$"(&3{instance.DefaultOverload.Target.GetMemberName()}&r)");
132+
133+
continue;
134+
}
135+
136+
instance.DefaultOverload = overload;
149137
}
138+
else
139+
{
140+
if (instance.Overloads.ContainsKey(commandOverloadAttribute.Name))
141+
{
142+
ApiLog.Error("Command Manager", $"Method &1{method.GetMemberName()}&r in command &1{instance.Name}&r" +
143+
$"cannot be added as an overload because an overload with the same name already exists.");
150144

151-
instance.Overloads.Add(commandOverloadAttribute.Name, overload);
145+
continue;
146+
}
147+
148+
instance.Overloads.Add(commandOverloadAttribute.Name, overload);
149+
}
152150
}
153151
}
154152

@@ -266,6 +264,20 @@ private static void OnCommand(CommandExecutingEventArgs ev)
266264
overload = command.DefaultOverload;
267265
}
268266

267+
if (overload.Permission != null && !player.HasPermissions(overload.Permission))
268+
{
269+
var response =
270+
CommandResponseFormatter.FormatMissingPermissionsFailure(overload.Permission, $"{command.Name} {overload.Name}",
271+
ev.CommandType);
272+
273+
ev.WriteError(response, "red");
274+
275+
ServerEvents.OnCommandExecuted(new(ev.Sender, ev.CommandType, null, ev.Arguments, false, response));
276+
277+
ListPool<string>.Shared.Return(args);
278+
return;
279+
}
280+
269281
line = string.Join(" ", args);
270282

271283
var tokens = ListPool<ICommandToken>.Shared.Rent();

LabExtended/Commands/CommandOverload.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,12 @@ public class CommandOverload
8181
/// Gets the overload's description.
8282
/// </summary>
8383
public string Description { get; internal set; }
84-
84+
85+
/// <summary>
86+
/// Gets the permission required to execute the overload.
87+
/// </summary>
88+
public string? Permission { get; internal set; }
89+
8590
/// <summary>
8691
/// Gets the overload's buffer.
8792
/// </summary>
@@ -122,7 +127,7 @@ public CommandOverload(MethodInfo target)
122127
Runner = RegularCommandRunner.Singleton;
123128
}
124129

125-
foreach (var parameter in parameters)
130+
foreach (var parameter in parameters!)
126131
{
127132
var builder = new CommandParameterBuilder(parameter);
128133

LabExtended/Commands/Custom/Despawn/DespawnCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ namespace LabExtended.Commands.Custom.Despawn;
2020
[Attributes.Command("despawn", "Despawns an object.")]
2121
public class DespawnCommand : CommandBase, IRemoteAdminCommand
2222
{
23-
[CommandOverload("Despawns an object that you're currently looking at.")]
23+
[CommandOverload("Despawns an object that you're currently looking at.", null)]
2424
public void RaycastOverload(
2525
[CommandParameter("Player", "The player of which camera will be used")] ExPlayer? originPlayer = null,
2626
[CommandParameter("Distance", "The maximum hit distance")] float distance = 50f)

0 commit comments

Comments
 (0)