Skip to content

Commit 157230b

Browse files
committed
Refactor and enhance command registry system
Moved CommandRegistry to a new location and improved its logic, including static and instance command registration, auto-registration on load, and case-insensitive command execution. Updated CommandData with parameter retrieval and improved error logging. Adjusted TestCommand usage to match new API and file structure. Cleaned up obsolete files and reorganized sample commands.
1 parent 8897c50 commit 157230b

File tree

8 files changed

+168
-85
lines changed

8 files changed

+168
-85
lines changed

Runtime/Core/CommandData.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@ namespace Commander.Core
66
{
77
public struct CommandData
88
{
9+
#region Properties
10+
911
public string CommandName { get; }
1012
public MethodInfo MethodData { get; }
1113
public object TargetClass { get; }
1214
public CommandFlags Flags { get; } // Set roles and flags?
1315

16+
#endregion
17+
18+
#region Constructors
19+
1420
public CommandData(string commandName, MethodInfo methodData,
1521
object targetClass, CommandFlags flags = CommandFlags.None)
1622
{
@@ -20,6 +26,24 @@ public CommandData(string commandName, MethodInfo methodData,
2026
Flags = flags;
2127
}
2228

29+
#endregion
30+
31+
#region Command Logic
32+
33+
/// <summary>
34+
/// Retrieves the parameters assigned to this command
35+
/// </summary>
36+
/// <returns></returns>
37+
public object[] GetParameters()
38+
{
39+
return MethodData.GetParameters();
40+
}
41+
42+
/// <summary>
43+
/// Tries to execute a method with given parameters
44+
/// </summary>
45+
/// <param name="args">Parameters of the method</param>
46+
/// <returns>Execution was successful</returns>
2347
public bool Execute(object[] args)
2448
{
2549
try
@@ -29,9 +53,11 @@ public bool Execute(object[] args)
2953
}
3054
catch (Exception e)
3155
{
32-
Debug.LogWarning($"Could not execute {CommandName}: " + e);
56+
Debug.LogWarning($"[CommandData] Could not execute '{CommandName}': " + e);
3357
return false;
3458
}
3559
}
60+
61+
#endregion
3662
}
3763
}

Runtime/Core/CommandFlags.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ public enum CommandFlags
66
None = 0,
77
Hidden = 1,
88
RequiresRole = 2
9-
// more command flags here...
9+
// more command flags here...?
1010
}
1111
}

Runtime/Core/CommandRegistry.cs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
using UnityEngine;
5+
6+
namespace Commander.Core
7+
{
8+
public static class CommandRegistry
9+
{
10+
#region Properties
11+
12+
// key = unqiue command name
13+
// value = CommandData
14+
private static Dictionary<string, CommandData> _registeredCommands =
15+
new Dictionary<string, CommandData>();
16+
17+
/// <summary>
18+
/// All command name keys and their CommandData value
19+
/// </summary>
20+
public static Dictionary<string, CommandData> RegisteredCommands
21+
{
22+
get { return _registeredCommands; }
23+
}
24+
25+
#endregion
26+
27+
#region Lifecycle
28+
29+
/// <summary>
30+
/// Clears all commands within the Registry
31+
/// </summary>
32+
public static void ClearCommands()
33+
{
34+
_registeredCommands.Clear();
35+
}
36+
37+
/// <summary>
38+
/// Called before the first scene loads. Registers all application static commands
39+
/// </summary>
40+
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
41+
private static void AutoRegister()
42+
{
43+
ClearCommands();
44+
RegisterStaticCommands();
45+
}
46+
47+
#endregion
48+
49+
#region Command Registering
50+
51+
/// <summary>
52+
/// Registers a MonoBehaviour class which includes the Command Attribute.
53+
/// </summary>
54+
/// <param name="targetClass">Class that contains Command Methods</param>
55+
public static void RegisterInstanceCommands(object targetClass = null)
56+
{
57+
var targetMethods = targetClass.GetType().GetMethods(
58+
BindingFlags.Instance |
59+
BindingFlags.Public |
60+
BindingFlags.NonPublic
61+
);
62+
63+
foreach (var methodInfo in targetMethods)
64+
{
65+
// Check if method has attribute
66+
var cmdAttribute = methodInfo.GetCustomAttribute<CommandAttribute>();
67+
if (cmdAttribute == null)
68+
{
69+
continue;
70+
}
71+
72+
// Use method name if commandname not present
73+
string cmdName = cmdAttribute.Name?.ToLower().Trim() switch
74+
{
75+
string s when s.Length > 0 => s,
76+
_ => methodInfo.Name
77+
};
78+
79+
if (_registeredCommands.ContainsKey(cmdName))
80+
{
81+
Debug.Log($"[CommandRegistry] Comamnd already registered with name '{cmdName}'");
82+
continue;
83+
}
84+
85+
// Assign value of dictionary as new CommandData
86+
_registeredCommands[cmdName] = new CommandData(cmdName, methodInfo, targetClass);
87+
Debug.Log($"[CommandRegistry] Registered Command '{cmdName}'");
88+
}
89+
}
90+
91+
/// <summary>
92+
/// Registers all static classes found within the App Domain. Called at initialisation
93+
/// </summary>
94+
public static void RegisterStaticCommands()
95+
{
96+
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
97+
{
98+
foreach (var type in assembly.GetTypes())
99+
{
100+
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
101+
foreach (var method in methods)
102+
{
103+
var attr = method.GetCustomAttribute<CommandAttribute>();
104+
if (attr == null)
105+
{
106+
continue;
107+
}
108+
string cmdName = string.IsNullOrWhiteSpace(attr.Name) ? method.Name : attr.Name;
109+
_registeredCommands[cmdName] = new CommandData(cmdName, method, null);
110+
Debug.Log($"[CommandRegistry] Registered Static Command '{cmdName}'");
111+
}
112+
}
113+
}
114+
}
115+
116+
#endregion
117+
118+
#region Command Execution
119+
120+
public static bool TryExecuteCommand(string commandName, object[] args)
121+
{
122+
// Ensures no character-case mistakes occur
123+
commandName = commandName.ToLower();
124+
125+
// Check if command even exists
126+
if (!_registeredCommands.TryGetValue(commandName, out var data))
127+
{
128+
Debug.Log($"[CommandRegistry] No command with name '{commandName}'");
129+
return false;
130+
}
131+
132+
// Try executing command from CommandData
133+
return data.Execute(args);
134+
}
135+
136+
#endregion
137+
}
138+
}
File renamed without changes.

Runtime/Core/Registry.meta

Lines changed: 0 additions & 8 deletions
This file was deleted.

Runtime/Core/Registry/CommandRegistry.cs

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@ public class TestCommand : MonoBehaviour
66
{
77
void Awake()
88
{
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" });
9+
CommandRegistry.RegisterInstanceCommands(this);
10+
CommandRegistry.TryExecuteCommand("publictestcommand", new object[2] { "Test", "test" });
1311
}
1412

1513
[Command("PublicTestCommand", CommandRole.Any)]
@@ -23,9 +21,4 @@ private void PrivateMyCommand(int a, string b)
2321
{
2422
Debug.Log($"Command executed with parameters: a = {a}, b = {b}");
2523
}
26-
27-
private void NonCommandMethod()
28-
{
29-
Debug.Log("This method is not a command and will not be registered.");
30-
}
3124
}
File renamed without changes.

0 commit comments

Comments
 (0)