Skip to content
This repository was archived by the owner on Nov 7, 2024. It is now read-only.

Commit 77aa9c1

Browse files
author
DaZombieKiller
committed
Commit project files
1 parent feee10a commit 77aa9c1

11 files changed

Lines changed: 272 additions & 0 deletions

File tree

Build/Module.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Module>
3+
<Name>UnityPluginManager</Name>
4+
<DefaultStartupProject>PluginManager.Installer</DefaultStartupProject>
5+
<Packages>
6+
<Package Uri="https-nuget://www.nuget.org/api/v2/|Mono.Cecil" Folder="Dependencies/Mono.Cecil" GitRef="0.9.6.4" />
7+
</Packages>
8+
</Module>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project Name="PluginManager.Installer" Path="Source/PluginManager.Installer" Type="Console">
3+
<References>
4+
<!-- GAC Assemblies -->
5+
<Reference Include="System" />
6+
<Reference Include="System.Core" />
7+
8+
<!-- NuGet -->
9+
<Reference Include="Mono.Cecil" />
10+
</References>
11+
12+
<Files>
13+
<!-- C# Sources -->
14+
<Compile Include="Program.cs" />
15+
</Files>
16+
</Project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project Name="PluginManager" Path="Source/PluginManager" Type="Library">
3+
<References>
4+
<!-- GAC Assemblies -->
5+
<Reference Include="System" />
6+
<Reference Include="System.Core" />
7+
8+
<!-- Unity API -->
9+
<Reference Include="UnityEngine" />
10+
</References>
11+
12+
<!-- The framework version must be v3.5 or lower,
13+
because that's the only one supported by all
14+
versions of Unity. -->
15+
<Properties>
16+
<FrameworkVersions>
17+
<Platform Name="Windows"><Version>v3.5</Version></Platform>
18+
<Platform Name="Linux"><Version>v3.5</Version></Platform>
19+
<Platform Name="MacOS"><Version>v3.5</Version></Platform>
20+
</FrameworkVersions>
21+
</Properties>
22+
23+
<Files>
24+
<Compile Include="PluginManager.cs" />
25+
<Compile Include="Plugin/Attributes.cs" />
26+
<Compile Include="Plugin/Extensions/Extensions.cs" />
27+
</Files>
28+
</Project>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ExternalProject Name="UnityEngine">
3+
<Binary
4+
Name="UnityEngine"
5+
Path="Managed/UnityEngine.dll"
6+
/>
7+
</ExternalProject>

Managed/.gitkeep

Whitespace-only changes.

Protobuild.exe

194 KB
Binary file not shown.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
5+
using Mono.Cecil;
6+
using Mono.Cecil.Cil;
7+
8+
namespace PluginManager.Installer
9+
{
10+
internal class Program
11+
{
12+
/// <summary>The program entry point.</summary>
13+
private static void Main()
14+
{
15+
string enginePath, managedPath;
16+
var resolver = new DefaultAssemblyResolver();
17+
18+
var enginePaths = Directory.EnumerateFiles(
19+
"./", "UnityEngine.dll", SearchOption.AllDirectories).ToArray();
20+
21+
if (enginePaths.Length < 1)
22+
throw new FileNotFoundException("UnityEngine.dll");
23+
else
24+
{
25+
// use the first instance of UnityEngine.dll found
26+
enginePath = enginePaths.First();
27+
managedPath = Path.GetDirectoryName(enginePath) ?? string.Empty;
28+
29+
// add the Managed directory as a search path
30+
resolver.AddSearchDirectory(managedPath);
31+
32+
// copy the plugin dlls to the managed path
33+
if (File.Exists("PluginManager.dll"))
34+
File.Copy("PluginManager.dll", Path.Combine(managedPath, "PluginManager.dll"), true);
35+
}
36+
37+
// load the UnityEngine module
38+
var engine = ModuleDefinition.ReadModule(
39+
new MemoryStream(File.ReadAllBytes(enginePath)),
40+
new ReaderParameters { AssemblyResolver = resolver });
41+
var gameObject = engine.GetType("UnityEngine", "GameObject");
42+
43+
// load the PluginManager module
44+
var plugin = ModuleDefinition.ReadModule(Path.Combine(managedPath, "PluginManager.dll"));
45+
var manager = plugin.GetType("PluginManager", "PluginManager");
46+
47+
// has UnityEngine already been patched?
48+
if (gameObject.Methods.Any(m => m.Name == ".cctor"))
49+
{
50+
// remove the static constructor
51+
gameObject.Methods.Remove(
52+
gameObject.Methods.Single(m => m.Name == ".cctor"));
53+
54+
// save changes
55+
engine.Write(enginePath);
56+
57+
Console.WriteLine("Plugin manager uninstalled.");
58+
Console.WriteLine("Press any key to exit.");
59+
Console.ReadKey();
60+
return;
61+
}
62+
63+
// create a static constructor
64+
var cctor = new MethodDefinition(".cctor",
65+
MethodAttributes.Private | MethodAttributes.Static |
66+
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
67+
MethodAttributes.RTSpecialName | MethodAttributes.ReuseSlot, engine.TypeSystem.Void);
68+
69+
var il = cctor.Body.GetILProcessor();
70+
cctor.Body.Instructions.Add(il.Create(OpCodes.Call,
71+
engine.Import(manager.Methods.Single(m => m.Name == "Initialize"))));
72+
cctor.Body.Instructions.Add(il.Create(OpCodes.Ret));
73+
74+
// add the static constructor
75+
gameObject.Methods.Add(cctor);
76+
77+
// save changes
78+
engine.Write(enginePath);
79+
Console.WriteLine("Plugin manager installed.");
80+
Console.WriteLine("Press any key to exit.");
81+
Console.ReadKey();
82+
}
83+
}
84+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using System;
2+
3+
namespace PluginManager.Plugin
4+
{
5+
/// <summary></summary>
6+
[AttributeUsage(AttributeTargets.Class)]
7+
public class OnGameInitAttribute : Attribute {}
8+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using UnityEngine;
3+
4+
namespace PluginManager.Plugin.Extensions
5+
{
6+
/// <summary></summary>
7+
public static class Extensions
8+
{
9+
/// <summary></summary>
10+
/// <param name="self"></param>
11+
/// <param name="component"></param>
12+
public static void RemoveComponent(this GameObject self, Type component)
13+
{
14+
UnityEngine.Object.Destroy(self.GetComponent(component));
15+
}
16+
17+
/// <summary></summary>
18+
/// <param name="self"></param>
19+
/// <typeparam name="T"></typeparam>
20+
public static void RemoveComponent<T>(this GameObject self)
21+
{
22+
RemoveComponent(self, typeof(T));
23+
}
24+
}
25+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.IO;
3+
using System.Reflection;
4+
using System.Collections.Generic;
5+
6+
using UnityEngine;
7+
using PluginManager.Plugin;
8+
9+
namespace PluginManager
10+
{
11+
/// <summary></summary>
12+
public class PluginManager : MonoBehaviour
13+
{
14+
// Static fields
15+
// --------------------------------------------------------------------------------
16+
private static bool _initialized;
17+
private static GameObject _gameObject;
18+
private static List<Type> _types;
19+
20+
// Static methods
21+
// --------------------------------------------------------------------------------
22+
/// <summary></summary>
23+
public static void Initialize()
24+
{
25+
if (_initialized) return;
26+
27+
_gameObject = new GameObject("Plugin Manager");
28+
_gameObject.AddComponent<PluginManager>();
29+
30+
DontDestroyOnLoad(_gameObject);
31+
32+
_initialized = true;
33+
}
34+
35+
// Methods
36+
// --------------------------------------------------------------------------------
37+
private void Awake()
38+
{
39+
// load all plugins
40+
LoadPlugins();
41+
}
42+
43+
private static void LoadPlugins()
44+
{
45+
if (_types != null) _types.Clear();
46+
else _types = new List<Type>();
47+
48+
if (Directory.Exists("./Plugins"))
49+
foreach (var path in Directory.GetFiles("./Plugins", "*.dll"))
50+
{
51+
try
52+
{
53+
// load plugin
54+
var module = Assembly.LoadFile(path);
55+
56+
// search for behaviours
57+
foreach (var type in module.GetTypes())
58+
{
59+
if (type.IsSubclassOf(typeof(MonoBehaviour)) &&
60+
type.IsDefined(typeof(OnGameInitAttribute), false))
61+
{
62+
_types.Add(type);
63+
}
64+
}
65+
}
66+
catch (BadImageFormatException)
67+
{
68+
Debug.LogErrorFormat("Bad plugin: {0}", path);
69+
}
70+
}
71+
72+
foreach (var t in _types)
73+
{
74+
if (_gameObject.GetComponent(t))
75+
Destroy(_gameObject.GetComponent(t));
76+
_gameObject.AddComponent(t);
77+
}
78+
}
79+
80+
private void Update()
81+
{
82+
// reload plugins with end key
83+
if (Input.GetKeyDown(KeyCode.End))
84+
LoadPlugins();
85+
}
86+
}
87+
}

0 commit comments

Comments
 (0)