This repository has been archived by the owner on May 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PluginCommandManager.cs
89 lines (76 loc) · 3.69 KB
/
PluginCommandManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using Dalamud.Game.Command;
using Dalamud.Plugin;
using FFLogsLookup.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using static Dalamud.Game.Command.CommandInfo;
// ReSharper disable ForCanBeConvertedToForeach
namespace FFLogsLookup
{
public class PluginCommandManager<THost> : IDisposable
{
private readonly DalamudPluginInterface pluginInterface;
private readonly (string, CommandInfo)[] pluginCommands;
private readonly THost host;
public PluginCommandManager(THost host, DalamudPluginInterface pluginInterface)
{
this.pluginInterface = pluginInterface;
this.host = host;
this.pluginCommands = host.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)
.Where(method => method.GetCustomAttribute<CommandAttribute>() != null)
.SelectMany(GetCommandInfoTuple)
.ToArray();
AddCommandHandlers();
}
// http://codebetter.com/patricksmacchia/2008/11/19/an-easy-and-efficient-way-to-improve-net-code-performances/
// Benchmarking this myself gave similar results, so I'm doing this to somewhat counteract using reflection to access command attributes.
// I like the convenience of attributes, but in principle it's a bit slower to use them as opposed to just initializing CommandInfos directly.
// It's usually sub-1 millisecond anyways, though. It probably doesn't matter at all.
private void AddCommandHandlers()
{
for (var i = 0; i < this.pluginCommands.Length; i++)
{
var (command, commandInfo) = this.pluginCommands[i];
this.pluginInterface.CommandManager.AddHandler(command, commandInfo);
}
}
private void RemoveCommandHandlers()
{
for (var i = 0; i < this.pluginCommands.Length; i++)
{
var (command, _) = this.pluginCommands[i];
this.pluginInterface.CommandManager.RemoveHandler(command);
}
}
private IEnumerable<(string, CommandInfo)> GetCommandInfoTuple(MethodInfo method)
{
var handlerDelegate = (HandlerDelegate)Delegate.CreateDelegate(typeof(HandlerDelegate), this.host, method);
var command = handlerDelegate.Method.GetCustomAttribute<CommandAttribute>();
var aliases = handlerDelegate.Method.GetCustomAttribute<AliasesAttribute>();
var helpMessage = handlerDelegate.Method.GetCustomAttribute<HelpMessageAttribute>();
var doNotShowInHelp = handlerDelegate.Method.GetCustomAttribute<DoNotShowInHelpAttribute>();
var commandInfo = new CommandInfo(handlerDelegate)
{
HelpMessage = helpMessage?.HelpMessage ?? string.Empty,
ShowInHelp = doNotShowInHelp == null,
};
// Create list of tuples that will be filled with one tuple per alias, in addition to the base command tuple.
var commandInfoTuples = new List<(string, CommandInfo)> { (command.Command, commandInfo) };
if (aliases != null)
{
// ReSharper disable once LoopCanBeConvertedToQuery
for (var i = 0; i < aliases.Aliases.Length; i++)
{
commandInfoTuples.Add((aliases.Aliases[i], commandInfo));
}
}
return commandInfoTuples;
}
public void Dispose()
{
RemoveCommandHandlers();
}
}
}