├── .gitmodules
├── Build.All.bat
├── DotNet35.props
├── LICENSE
├── Managed.Games
├── Assemblies.props
├── SlimeRancher
│ └── .gitkeep
└── Universal
│ └── .gitkeep
├── Managed.UnityEngine
├── Managed
│ └── .gitkeep
├── UnityEngine.2017.props
├── UnityEngine.4.props
├── UnityEngine.5.props
└── UnityEngine.Auto.props
├── PluginManager.Core
├── Extensions
│ ├── GameObject.cs
│ ├── Texture.cs
│ ├── Texture2D.cs
│ └── TextureFormat.cs
├── OnGameInitAttribute.cs
├── PluginManager.Core.csproj
├── PluginManager.cs
└── Properties
│ └── AssemblyInfo.cs
├── PluginManager.Setup
├── PathDiscovery.cs
├── PluginManager.Setup.csproj
└── Program.cs
├── PluginManager.sln
├── PluginManager.sln.DotSettings
└── README.md
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Plugin.Templates/Template.NET35"]
2 | path = Plugin.Templates/Template.NET35
3 | url = https://github.com/UnityPluginManager/Template.NET35.git
4 | [submodule "Plugin.Templates/Template.NET46"]
5 | path = Plugin.Templates/Template.NET46
6 | url = https://github.com/UnityPluginManager/Template.NET46.git
7 | [submodule "Plugin.Projects/Universal.SamplePlugin"]
8 | path = Plugin.Projects/Universal.SamplePlugin
9 | url = https://github.com/UnityPluginManager/Universal.SamplePlugin.git
10 | [submodule "Plugin.Projects/SlimeRancher.DebugMenu"]
11 | path = Plugin.Projects/SlimeRancher.DebugMenu
12 | url = https://github.com/UnityPluginManager/SlimeRancher.DebugMenu.git
13 |
--------------------------------------------------------------------------------
/Build.All.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | set BaseDir=%cd%
4 |
5 | cd %BaseDir%\PluginManager.Core
6 | dotnet build
7 |
8 | cd %BaseDir%\PluginManager.Setup
9 | dotnet build
10 |
11 | echo Press any key to exit . . .
12 | pause > nul
13 |
--------------------------------------------------------------------------------
/DotNet35.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | $(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 UPM Team
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Managed.Games/Assemblies.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)\$(TargetGame)\Assembly-CSharp.dll
5 | False
6 |
7 |
8 |
9 |
10 |
11 | $(MSBuildThisFileDirectory)\$(TargetGame)\Assembly-UnityScript.dll
12 | False
13 |
14 |
15 |
16 |
17 |
18 | $(MSBuildThisFileDirectory)\$(TargetGame)\Assembly-Boo.dll
19 | False
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Managed.Games/SlimeRancher/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnityPluginManager/PluginManager/c4268fb527861415661827557eea601f22bb7b51/Managed.Games/SlimeRancher/.gitkeep
--------------------------------------------------------------------------------
/Managed.Games/Universal/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnityPluginManager/PluginManager/c4268fb527861415661827557eea601f22bb7b51/Managed.Games/Universal/.gitkeep
--------------------------------------------------------------------------------
/Managed.UnityEngine/Managed/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnityPluginManager/PluginManager/c4268fb527861415661827557eea601f22bb7b51/Managed.UnityEngine/Managed/.gitkeep
--------------------------------------------------------------------------------
/Managed.UnityEngine/UnityEngine.2017.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UI.dll
5 | False
6 |
7 |
8 |
9 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.AccessibilityModule.dll
10 | False
11 |
12 |
13 |
14 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ParticleSystemModule.dll
15 | False
16 |
17 |
18 |
19 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.PhysicsModule.dll
20 | False
21 |
22 |
23 |
24 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.VehiclesModule.dll
25 | False
26 |
27 |
28 |
29 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ClothModule.dll
30 | False
31 |
32 |
33 |
34 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.AIModule.dll
35 | False
36 |
37 |
38 |
39 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.AnimationModule.dll
40 | False
41 |
42 |
43 |
44 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.TextRenderingModule.dll
45 | False
46 |
47 |
48 |
49 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UIModule.dll
50 | False
51 |
52 |
53 |
54 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.TerrainPhysicsModule.dll
55 | False
56 |
57 |
58 |
59 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.IMGUIModule.dll
60 | False
61 |
62 |
63 |
64 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ClusterInputModule.dll
65 | False
66 |
67 |
68 |
69 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ClusterRendererModule.dll
70 | False
71 |
72 |
73 |
74 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UNETModule.dll
75 | False
76 |
77 |
78 |
79 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.DirectorModule.dll
80 | False
81 |
82 |
83 |
84 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityAnalyticsModule.dll
85 | False
86 |
87 |
88 |
89 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.PerformanceReportingModule.dll
90 | False
91 |
92 |
93 |
94 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityConnectModule.dll
95 | False
96 |
97 |
98 |
99 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.WebModule.dll
100 | False
101 |
102 |
103 |
104 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ARModule.dll
105 | False
106 |
107 |
108 |
109 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.VRModule.dll
110 | False
111 |
112 |
113 |
114 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UIElementsModule.dll
115 | False
116 |
117 |
118 |
119 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.StyleSheetsModule.dll
120 | False
121 |
122 |
123 |
124 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.AssetBundleModule.dll
125 | False
126 |
127 |
128 |
129 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.AudioModule.dll
130 | False
131 |
132 |
133 |
134 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.CrashReportingModule.dll
135 | False
136 |
137 |
138 |
139 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.GameCenterModule.dll
140 | False
141 |
142 |
143 |
144 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.GridModule.dll
145 | False
146 |
147 |
148 |
149 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ImageConversionModule.dll
150 | False
151 |
152 |
153 |
154 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.InputModule.dll
155 | False
156 |
157 |
158 |
159 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.JSONSerializeModule.dll
160 | False
161 |
162 |
163 |
164 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ParticlesLegacyModule.dll
165 | False
166 |
167 |
168 |
169 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.Physics2DModule.dll
170 | False
171 |
172 |
173 |
174 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.ScreenCaptureModule.dll
175 | False
176 |
177 |
178 |
179 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.SharedInternalsModule.dll
180 | False
181 |
182 |
183 |
184 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.SpriteMaskModule.dll
185 | False
186 |
187 |
188 |
189 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.SpriteShapeModule.dll
190 | False
191 |
192 |
193 |
194 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.TerrainModule.dll
195 | False
196 |
197 |
198 |
199 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.TilemapModule.dll
200 | False
201 |
202 |
203 |
204 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityWebRequestModule.dll
205 | False
206 |
207 |
208 |
209 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityWebRequestAudioModule.dll
210 | False
211 |
212 |
213 |
214 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityWebRequestTextureModule.dll
215 | False
216 |
217 |
218 |
219 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UnityWebRequestWWWModule.dll
220 | False
221 |
222 |
223 |
224 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.VideoModule.dll
225 | False
226 |
227 |
228 |
229 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.WindModule.dll
230 | False
231 |
232 |
233 |
234 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.CoreModule.dll
235 | False
236 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/Managed.UnityEngine/UnityEngine.4.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Managed.UnityEngine/UnityEngine.5.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.UI.dll
5 | False
6 |
7 |
8 |
9 | $(MSBuildThisFileDirectory)\Managed\UnityEngine.dll
10 | False
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Managed.UnityEngine/UnityEngine.Auto.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | $(MSBuildThisFileDirectory)\UnityEngine.5.props
6 |
7 |
8 |
9 |
10 | $(MSBuildThisFileDirectory)\UnityEngine.2017.props
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/PluginManager.Core/Extensions/GameObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using JetBrains.Annotations;
3 | using UnityEngine;
4 |
5 | namespace PluginManager.Core.Extensions
6 | {
7 | public static class GameObjectExtensions
8 | {
9 | [PublicAPI]
10 | public static void RemoveComponent(this GameObject self, Type component)
11 | {
12 | UnityEngine.Object.Destroy(self.GetComponent(component));
13 | }
14 |
15 | [PublicAPI]
16 | public static void RemoveComponent(this GameObject self)
17 | {
18 | self.RemoveComponent(typeof(T));
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/PluginManager.Core/Extensions/Texture.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Annotations;
2 | using UnityEngine;
3 |
4 | namespace PluginManager.Core.Extensions
5 | {
6 | public static class TextureExtensions
7 | {
8 | [PublicAPI]
9 | public static Vector2 GetDimensions(this Texture self)
10 | {
11 | return new Vector2(self.width, self.height);
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/PluginManager.Core/Extensions/Texture2D.cs:
--------------------------------------------------------------------------------
1 | using JetBrains.Annotations;
2 | using UnityEngine;
3 |
4 | namespace PluginManager.Core.Extensions
5 | {
6 | public static class Texture2DExtensions
7 | {
8 | [PublicAPI]
9 | public static Texture2D ToReadable(this Texture2D self)
10 | {
11 | var newTexture = new Texture2D(self.width, self.height);
12 | RenderTexture prevRender = RenderTexture.active;
13 |
14 | RenderTexture newRender = RenderTexture.GetTemporary(self.width, self.height, 0,
15 | self.format.ToRenderTextureFormat(), RenderTextureReadWrite.Linear);
16 |
17 | Graphics.Blit(self, newRender);
18 | RenderTexture.active = newRender;
19 |
20 | newTexture.ReadPixels(new Rect(0, 0, self.width, self.height), 0, 0);
21 | newTexture.Apply();
22 |
23 | RenderTexture.active = prevRender;
24 | RenderTexture.ReleaseTemporary(newRender);
25 |
26 | return newTexture;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/PluginManager.Core/Extensions/TextureFormat.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using JetBrains.Annotations;
3 | using UnityEngine;
4 |
5 | namespace PluginManager.Core.Extensions
6 | {
7 | public static class TextureFormatExtensions
8 | {
9 | /// Converts a TextureFormat to a RenderTextureFormat.
10 | [PublicAPI]
11 | [SuppressMessage("ReSharper", "SwitchStatementMissingSomeCases")]
12 | public static RenderTextureFormat ToRenderTextureFormat(this TextureFormat self)
13 | {
14 | switch (self)
15 | {
16 | case TextureFormat.ARGB32: return RenderTextureFormat.ARGB32;
17 | case TextureFormat.RGB565: return RenderTextureFormat.RGB565;
18 | case TextureFormat.ARGB4444: return RenderTextureFormat.ARGB4444;
19 | case TextureFormat.RGFloat: return RenderTextureFormat.RGFloat;
20 | case TextureFormat.RGHalf: return RenderTextureFormat.RGHalf;
21 | case TextureFormat.RFloat: return RenderTextureFormat.RFloat;
22 | case TextureFormat.RHalf: return RenderTextureFormat.RHalf;
23 | case TextureFormat.R8: return RenderTextureFormat.R8;
24 | case TextureFormat.BGRA32: return RenderTextureFormat.BGRA32;
25 | case TextureFormat.RG16: return RenderTextureFormat.RG16;
26 | default: return RenderTextureFormat.Default;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/PluginManager.Core/OnGameInitAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using JetBrains.Annotations;
3 | using UnityEngine;
4 |
5 | namespace PluginManager.Core
6 | {
7 | [AttributeUsage(AttributeTargets.Class)]
8 | [BaseTypeRequired(typeof(MonoBehaviour))]
9 | public class OnGameInitAttribute : Attribute
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/PluginManager.Core/PluginManager.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net35
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/PluginManager.Core/PluginManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Reflection;
5 | using JetBrains.Annotations;
6 | using UnityEngine;
7 |
8 | namespace PluginManager.Core
9 | {
10 | public class PluginManager : MonoBehaviour
11 | {
12 | readonly string pluginDirectory = Path.Combine(Environment.CurrentDirectory, "Plugins");
13 |
14 | [UsedImplicitly]
15 | internal static void Initialize()
16 | {
17 | var gameObject = new GameObject("UPM Root");
18 | DontDestroyOnLoad(gameObject.transform.root);
19 | gameObject.AddComponent();
20 | }
21 |
22 | void Awake()
23 | {
24 | if (!Directory.Exists(pluginDirectory)) return;
25 |
26 | foreach (string fileName in Directory.GetFiles(pluginDirectory, "*.dll", SearchOption.AllDirectories))
27 | {
28 | try
29 | {
30 | Assembly plugin = Assembly.LoadFile(Path.GetFullPath(fileName));
31 |
32 | foreach (Type component in plugin.GetTypes()
33 | .Where(t => t.IsSubclassOf(typeof(MonoBehaviour)))
34 | .Where(t => t.IsDefined(typeof(OnGameInitAttribute), false)))
35 | {
36 | var componentObject = new GameObject(plugin.FullName);
37 | componentObject.transform.SetParent(transform);
38 | componentObject.AddComponent(component);
39 | }
40 | }
41 | catch (Exception e)
42 | {
43 | Debug.LogError(e.ToString());
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/PluginManager.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | [assembly: InternalsVisibleTo("UnityEngine")]
4 | [assembly: InternalsVisibleTo("UnityEngine.CoreModule")]
5 |
--------------------------------------------------------------------------------
/PluginManager.Setup/PathDiscovery.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Mono.Cecil;
4 |
5 | namespace PluginManager.Setup
6 | {
7 | static class PathDiscovery
8 | {
9 | public static string FindDataDirectory()
10 | {
11 | // test #1: Data
12 | if (Directory.Exists("Data")) return "Data";
13 |
14 | // test #2: ExecutableName_Data
15 | foreach (string fileName in Directory.EnumerateFiles(".", "*.exe"))
16 | {
17 | string exeName = Path.GetFileNameWithoutExtension(fileName);
18 | string potentialPath = $"{exeName}_Data";
19 | if (Directory.Exists(potentialPath)) return potentialPath;
20 | }
21 |
22 | // test #3: Any path ending in "_Data"
23 | foreach (string path in Directory.EnumerateDirectories(".", "*_Data"))
24 | return path;
25 |
26 | throw new DirectoryNotFoundException("Could not locate 'Data' directory.");
27 | }
28 |
29 | public static string FindManagedDirectory()
30 | {
31 | return Path.Combine(FindDataDirectory(), "Managed");
32 | }
33 |
34 | public static string GetAssemblyPath(IAssemblyResolver resolver, string name) =>
35 | GetAssemblyPath(resolver, name, null);
36 |
37 | public static string GetAssemblyPath(IAssemblyResolver resolver, string name, Version version) =>
38 | GetAssemblyPath(resolver, new AssemblyNameDefinition(name, version));
39 |
40 | public static string GetAssemblyPath(IAssemblyResolver resolver, AssemblyNameReference def)
41 | {
42 | using (AssemblyDefinition asm = resolver.Resolve(def))
43 | return asm.MainModule.FileName;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/PluginManager.Setup/PluginManager.Setup.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net46
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/PluginManager.Setup/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Text;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 |
8 | namespace PluginManager.Setup
9 | {
10 | static class Program
11 | {
12 | const string CoreLibrary = "PluginManager.Core.dll";
13 |
14 | static void Main()
15 | {
16 | string managedPath = PathDiscovery.FindManagedDirectory();
17 |
18 | var resolver = new DefaultAssemblyResolver();
19 | resolver.AddSearchDirectory(managedPath);
20 |
21 | Version version = GetUnityVersion();
22 |
23 | // as of Unity 2017.2, the UnityEngine assembly has been split into multiple assemblies
24 | // the assembly containing the GameObject class is UnityEngine.CoreModule
25 | string coreName = version.Major < 2017 || (version.Major == 2017 && version.Minor == 1)
26 | ? "UnityEngine"
27 | : "UnityEngine.CoreModule";
28 |
29 | string corePath = PathDiscovery.GetAssemblyPath(resolver, coreName);
30 | byte[] coreData = File.ReadAllBytes(corePath);
31 |
32 | Console.WriteLine("Unity {0} detected.", version);
33 |
34 | ModuleDefinition unityCore = ModuleDefinition.ReadModule(
35 | new MemoryStream(coreData),
36 | new ReaderParameters { AssemblyResolver = resolver });
37 |
38 | TypeDefinition gameObject = unityCore.GetType("UnityEngine", "GameObject");
39 |
40 | // UPM works by adding a static constructor to the GameObject class,
41 | // which calls an initialization function in PluginManager.Core
42 | SetStaticCtor(gameObject, GenStaticCtor(unityCore, il =>
43 | {
44 | ModuleDefinition upm = ModuleDefinition.ReadModule(CoreLibrary);
45 | TypeDefinition upmMain = upm.GetType("PluginManager.Core", "PluginManager");
46 | MethodDefinition upmInit = upmMain.Methods.Single(m => m.Name == "Initialize");
47 |
48 | il.Emit(OpCodes.Call, unityCore.ImportReference(upmInit));
49 | il.Emit(OpCodes.Ret);
50 |
51 | upm.Dispose();
52 | }));
53 |
54 | unityCore.Write(corePath);
55 |
56 | // We need to copy PluginManager.Core.dll into the Managed directory
57 | File.Copy(CoreLibrary, Path.Combine(managedPath, CoreLibrary), true);
58 |
59 | Console.WriteLine("UPM installed.");
60 | }
61 |
62 | /// Retrieves the version from the game files
63 | /// An instance of containing the game's Unity version
64 | /// Thrown when an unsupported version of Unity is in use
65 | static Version GetUnityVersion()
66 | {
67 | string dataPath = PathDiscovery.FindDataDirectory();
68 | var dataFiles = new[] { "globalgamemanagers", "mainData" };
69 |
70 | if (!dataFiles.Any(p => File.Exists(Path.Combine(dataPath, p))))
71 | throw new NotSupportedException("Unsupported Unity version.");
72 |
73 | string dataFile = dataFiles.First(p => File.Exists(Path.Combine(dataPath, p)));
74 | using (FileStream ggm = File.OpenRead(Path.Combine(dataPath, dataFile)))
75 | using (var reader = new BinaryReader(ggm))
76 | {
77 | reader.ReadUInt32(); // metadataSize
78 | reader.ReadUInt32(); // fileSize
79 | uint format = reader.ReadUInt32();
80 | reader.ReadUInt32(); // dataOffset
81 |
82 | if (format >= 9)
83 | reader.ReadUInt32(); // endianness
84 |
85 | if (7 <= format && format <= 13)
86 | reader.ReadUInt32(); // longObjectIDs
87 |
88 | var sb = new StringBuilder();
89 |
90 | for (;;)
91 | {
92 | byte b = reader.ReadByte();
93 | if (b == 0) break;
94 | sb.Append((char)b);
95 | }
96 |
97 | string[] split = sb.ToString().Split('.', 'b', 'f', 'p');
98 |
99 | return new Version
100 | (
101 | Convert.ToInt32(split.Length > 0 ? split[0] : "0"), // major
102 | Convert.ToInt32(split.Length > 1 ? split[1] : "0"), // minor
103 | Convert.ToInt32(split.Length > 2 ? split[2] : "0"), // build
104 |
105 | // do we really care about this?
106 | Convert.ToInt32(split.Length > 3 ? split[3] : "0") // revision
107 | );
108 | }
109 | }
110 |
111 | static MethodDefinition GenStaticCtor(ModuleDefinition module, Action generator)
112 | {
113 | var cctor = new MethodDefinition(".cctor",
114 | MethodAttributes.Private | MethodAttributes.Static |
115 | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
116 | MethodAttributes.RTSpecialName | MethodAttributes.ReuseSlot,
117 | module.TypeSystem.Void);
118 |
119 | generator(cctor.Body.GetILProcessor());
120 | return cctor;
121 | }
122 |
123 | static void ClearStaticCtors(TypeDefinition t)
124 | {
125 | foreach (MethodDefinition method in t.Methods
126 | .Where(m => m.Name == ".cctor")
127 | .ToList())
128 | {
129 | t.Methods.Remove(method);
130 | }
131 | }
132 |
133 | static void SetStaticCtor(TypeDefinition t, MethodDefinition cctor)
134 | {
135 | ClearStaticCtors(t);
136 | t.Methods.Add(cctor);
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/PluginManager.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.0.0
5 | MinimumVisualStudioVersion = 10.0.0.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginManager.Setup", "PluginManager.Setup\PluginManager.Setup.csproj", "{01C46972-F038-4C03-BC5F-BD6223FF6476}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginManager.Core", "PluginManager.Core\PluginManager.Core.csproj", "{BABD6EBF-3A33-4F77-B751-DCD0C5F5E95B}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {01C46972-F038-4C03-BC5F-BD6223FF6476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {01C46972-F038-4C03-BC5F-BD6223FF6476}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {01C46972-F038-4C03-BC5F-BD6223FF6476}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {01C46972-F038-4C03-BC5F-BD6223FF6476}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {BABD6EBF-3A33-4F77-B751-DCD0C5F5E95B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {BABD6EBF-3A33-4F77-B751-DCD0C5F5E95B}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {BABD6EBF-3A33-4F77-B751-DCD0C5F5E95B}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {BABD6EBF-3A33-4F77-B751-DCD0C5F5E95B}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/PluginManager.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | Implicit
3 | Implicit
4 | True
5 | True
6 | True
7 | True
8 | True
9 | True
10 | True
11 | True
12 | True
13 | False
14 | True
15 | False
16 | UseVarWhenEvident
17 | UseVarWhenEvident
18 | UseVarWhenEvident
19 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
20 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
21 | True
22 | True
23 | True
24 | True
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Unity Plugin Manager
2 | ## Introduction
3 | Unity Plugin Manager (herein, UPM) is a tool for creating plugins and mods for games developed with the Unity engine.
4 |
5 | ## How it works
6 | UPM injects a static constructor into the GameObject class found within the UnityEngine namespace. This way, it is able to execute code before anything else in the game. Using this, it loads plugins from a folder named "Plugins" in the game's folder, and instantiates any MonoBehaviour derivatives with the [OnGameInit] attribute.
7 |
8 | ## Compiling
9 | In order to build UPM or create plugins, you will need the [.NET Core SDK](https://www.microsoft.com/net/core) and at least one of the following:
10 |
11 | * An installation of Unity 5.x or 2017.x
12 | * A game developed in Unity 5.x or 2017.x
13 |
14 | Within the UPM repository is a directory named `Managed.UnityEngine`. This directory needs to contain specific files from one of the aforementioned prerequisites.
15 |
16 | ### Option A: Unity Installation
17 | 1. Browse to your Unity installation directory (usually `C:\Program Files\Unity [version]\Editor`)
18 | 2. Browse to `Data\Managed` and copy `UnityEngine.dll` to the `Managed.UnityEngine\Managed` directory in the UPM repository
19 | 4. If it exists, browse to `Data\Managed\UnityEngine` and copy everything _except_ UnityEngine.dll to the `Managed.UnityEngine\Managed` directory in the UPM repository
20 | 5. Browse to `Data\UnityExtensions\Unity\GUISystem\Standalone` and copy `UnityEngine.UI.dll` to the `Managed.UnityEngine\Managed` directory in the UPM repository
21 |
22 | ### Option B: Game
23 | 1. Browse to the game's `Managed` directory (usually inside the game's `Data` folder)
24 | 2. Copy every file with `UnityEngine` in its name to the `Managed.UnityEngine\Managed` directory in the UPM repository
25 |
26 | ---
27 |
28 | You should now be able to compile UPM by either using `Build.All.bat`, `PluginManager.sln` or manually calling `dotnet build` in the appropriate directories.
29 |
30 | ## Usage
31 | After building UPM, you should have _at least_ the following files:
32 |
33 | * PluginManager.Setup.exe (`PluginManager.Setup/bin/...`)
34 | * PluginManager.Core.dll (`PluginManager.Core/bin/...`)
35 | * Mono.Cecil.dll (`PluginManager.Setup/bin/...`)
36 |
37 | Any other files are not necessary for usage of UPM.
38 |
39 | Place the aforementioned files into the directory where your target game is located, and run `PluginManager.Setup.exe` (using Mono to do so, if not on Windows)
40 |
41 | If UPM installed successfully, you should see a message stating `UPM installed.`
42 |
43 | You are now free to create a `Plugins` directory and place your plugins in there.
44 |
45 | ## Creating plugins
46 | The creation of plugins is a relatively simple process.
47 |
48 | 1. Make a new folder for your target game in the `Managed.Games` folder, if one does not exist
49 | 2. Put the `Assembly-CSharp.dll`, `Assembly-UnityScript.dll` and/or `Assembly-Boo.dll` files from your target game in that folder, if they are present in its `Managed` folder
50 | 3. Make a new folder for your plugin in the `Plugin.Projects` folder
51 | 4. Copy one of the templates into that folder (NET46 is only for Unity 2017 projects using the new Mono runtime!)
52 | 5. Edit Config.props to point to your target game
53 |
54 | You can compile your plugin by opening a command prompt in its folder and entering `dotnet build`.
55 |
56 | Refer to the [sample plugin](https://github.com/UnityPluginManager/Universal.SamplePlugin) as an example of how to get started.
57 |
--------------------------------------------------------------------------------