Skip to content

Commit 8897c50

Browse files
committed
Add command registry system and sample command usage
Introduced CommandData and CommandFlags for representing and flagging commands. Added CommandRegistry for registering and executing commands via reflection. Updated TestCommand to demonstrate command registration and execution. Minor improvements to CommandAttribute and CommandRoleAttribute constructors. Updated sample scene to include TestCommand usage.
1 parent a62adb4 commit 8897c50

File tree

11 files changed

+205
-6
lines changed

11 files changed

+205
-6
lines changed

Runtime/Attributes/CommandAttribute.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ public CommandAttribute(string name, CommandRole role)
7676
Descrption = string.Empty;
7777
}
7878

79+
/// <summary>
80+
/// Constructor for Command attribute with the command role only.
81+
/// </summary>
82+
/// <param name="role">This command's execution permission role</param>
83+
public CommandAttribute(CommandRole role)
84+
{
85+
Name = string.Empty;
86+
Role = CommandRole.Any;
87+
Descrption = string.Empty;
88+
}
89+
7990
#endregion
8091
}
8192
}

Runtime/Attributes/CommandRoleAttribute.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ public class CommandRoleAttribute : Attribute
1010
{
1111
public CommandRole Role { get; }
1212

13+
/// <summary>
14+
/// Default constructor for CommandRole attribute.
15+
/// </summary>
16+
/// <param name="role">This command's execution permission role</param>
1317
public CommandRoleAttribute(CommandRole role)
1418
{
1519
Role = role;

Runtime/Core/CommandData.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Reflection;
3+
using UnityEngine;
4+
5+
namespace Commander.Core
6+
{
7+
public struct CommandData
8+
{
9+
public string CommandName { get; }
10+
public MethodInfo MethodData { get; }
11+
public object TargetClass { get; }
12+
public CommandFlags Flags { get; } // Set roles and flags?
13+
14+
public CommandData(string commandName, MethodInfo methodData,
15+
object targetClass, CommandFlags flags = CommandFlags.None)
16+
{
17+
CommandName = commandName;
18+
MethodData = methodData;
19+
TargetClass = targetClass;
20+
Flags = flags;
21+
}
22+
23+
public bool Execute(object[] args)
24+
{
25+
try
26+
{
27+
MethodData.Invoke(TargetClass, args);
28+
return true;
29+
}
30+
catch (Exception e)
31+
{
32+
Debug.LogWarning($"Could not execute {CommandName}: " + e);
33+
return false;
34+
}
35+
}
36+
}
37+
}

Runtime/Core/CommandData.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Core/CommandFlags.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Commander.Core
2+
{
3+
[System.Flags]
4+
public enum CommandFlags
5+
{
6+
None = 0,
7+
Hidden = 1,
8+
RequiresRole = 2
9+
// more command flags here...
10+
}
11+
}

Runtime/Core/CommandFlags.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System.Collections.Generic;
2+
using System.Reflection;
3+
using UnityEngine;
4+
5+
namespace Commander.Core
6+
{
7+
public static class CommandRegistry
8+
{
9+
private static Dictionary<string, CommandData> _registeredCommands =
10+
new Dictionary<string, CommandData>();
11+
12+
public static Dictionary<string, CommandData> RegisteredCommands
13+
{
14+
get { return _registeredCommands; }
15+
}
16+
17+
public static void ClearCommands()
18+
{
19+
_registeredCommands.Clear();
20+
}
21+
22+
public static void RegisterCommands(object targetClass = null)
23+
{
24+
var targetMethods = targetClass.GetType().GetMethods(
25+
BindingFlags.Instance |
26+
BindingFlags.Public |
27+
BindingFlags.NonPublic
28+
);
29+
30+
foreach (var methodInfo in targetMethods)
31+
{
32+
// Check if method has attribute
33+
var cmdAttribute = methodInfo.GetCustomAttribute<CommandAttribute>();
34+
if (cmdAttribute == null)
35+
{
36+
continue;
37+
}
38+
39+
// Use method name if commandname not present
40+
string cmdName = cmdAttribute.Name?.Trim() switch
41+
{
42+
string s when s.Length > 0 => s,
43+
_ => methodInfo.Name
44+
};
45+
46+
// Assign value of dictionary as new CommandData
47+
_registeredCommands[cmdName] = new CommandData(cmdName, methodInfo, targetClass);
48+
Debug.Log($"[CommandRegistry] Registered Command {cmdName}");
49+
}
50+
Debug.Log($"[CommandRegistry] Registered Class {targetClass.GetType().Name} with {_registeredCommands.Count} methods");
51+
}
52+
53+
public static bool TryExecuteCommand(string commandName, object[] args)
54+
{
55+
// Check if command even exists
56+
if (!_registeredCommands.TryGetValue(commandName, out var data))
57+
{
58+
Debug.Log($"No command with name {commandName}");
59+
return false;
60+
}
61+
62+
// Try executing command from CommandData
63+
return data.Execute(args);
64+
}
65+
}
66+
}

Runtime/Core/Registry/CommandRegistry.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Core/TestCommand.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
11
using UnityEngine;
22
using Commander;
3+
using Commander.Core;
34

45
public class TestCommand : MonoBehaviour
56
{
6-
[HiddenCommand]
7-
[Command("TestCommand", CommandRole.Any)]
8-
public void Test()
7+
void Awake()
98
{
10-
9+
CommandRegistry.RegisterCommands(this);
10+
CommandRegistry.TryExecuteCommand("PublicTestCommand", new object[2] { 1, "String" });
11+
CommandRegistry.TryExecuteCommand("NoCommand", new object[2] { 1, "String" });
12+
CommandRegistry.TryExecuteCommand("PrivateTestCommand", new object[2] { 1, "String" });
1113
}
12-
}
14+
15+
[Command("PublicTestCommand", CommandRole.Any)]
16+
public void PublicMyCommand(int a, string b)
17+
{
18+
Debug.Log($"Command executed with parameters: a = {a}, b = {b}");
19+
}
20+
21+
[Command("PrivateTestCommand", CommandRole.Any)]
22+
private void PrivateMyCommand(int a, string b)
23+
{
24+
Debug.Log($"Command executed with parameters: a = {a}, b = {b}");
25+
}
26+
27+
private void NonCommandMethod()
28+
{
29+
Debug.Log("This method is not a command and will not be registered.");
30+
}
31+
}

0 commit comments

Comments
 (0)