-
Notifications
You must be signed in to change notification settings - Fork 49
/
PluginManager.cs
128 lines (107 loc) · 4.37 KB
/
PluginManager.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using IllusionPlugin;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace IllusionInjector
{
public static class PluginManager
{
private static List<IPlugin> _Plugins = null;
/// <summary>
/// Gets the list of loaded plugins and loads them if necessary.
/// </summary>
public static IEnumerable<IPlugin> Plugins
{
get
{
if(_Plugins == null)
{
LoadPlugins();
}
return _Plugins;
}
}
private static void LoadPlugins()
{
string pluginDirectory = Path.Combine(Environment.CurrentDirectory, "Plugins");
// Process.GetCurrentProcess().MainModule crashes the game and Assembly.GetEntryAssembly() is NULL,
// so we need to resort to P/Invoke
string exeName = Path.GetFileNameWithoutExtension(AppInfo.StartupPath);
Console.WriteLine(exeName);
_Plugins = new List<IPlugin>();
if (!Directory.Exists(pluginDirectory)) return;
String[] files = Directory.GetFiles(pluginDirectory, "*.dll");
foreach (var s in files)
{
_Plugins.AddRange(LoadPluginsFromFile(Path.Combine(pluginDirectory, s), exeName));
}
// DEBUG
Console.WriteLine("Running on Unity {0}", UnityEngine.Application.unityVersion);
Console.WriteLine("-----------------------------");
Console.WriteLine("Loading plugins from {0} and found {1}", pluginDirectory, _Plugins.Count);
Console.WriteLine("-----------------------------");
foreach (var plugin in _Plugins)
{
Console.WriteLine(" {0}: {1}", plugin.Name, plugin.Version);
}
Console.WriteLine("-----------------------------");
}
private static IEnumerable<IPlugin> LoadPluginsFromFile(string file, string exeName)
{
List<IPlugin> plugins = new List<IPlugin>();
if (!File.Exists(file) || !file.EndsWith(".dll", true, null))
return plugins;
try
{
Assembly assembly = Assembly.LoadFrom(file);
foreach (Type t in assembly.GetTypes())
{
if (t.GetInterface("IPlugin") != null)
{
try
{
IPlugin pluginInstance = Activator.CreateInstance(t) as IPlugin;
string[] filter = null;
if (pluginInstance is IEnhancedPlugin)
{
filter = ((IEnhancedPlugin)pluginInstance).Filter;
}
if(filter == null || Enumerable.Contains(filter, exeName, StringComparer.OrdinalIgnoreCase))
plugins.Add(pluginInstance);
}
catch (Exception e)
{
Console.WriteLine("[WARN] Could not load plugin {0} in {1}! {2}", t.FullName, Path.GetFileName(file), e);
}
}
}
}
catch (Exception e)
{
Console.WriteLine("[ERROR] Could not load {0}! {1}", Path.GetFileName(file), e);
}
return plugins;
}
public class AppInfo
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)]
private static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
private static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
public static string StartupPath
{
get
{
StringBuilder stringBuilder = new StringBuilder(260);
GetModuleFileName(NullHandleRef, stringBuilder, stringBuilder.Capacity);
return stringBuilder.ToString();
}
}
}
}
}