Browse Source

Merge 5683e3c502 into 9628195142

pull/11/merge
Quit GitHub 6 years ago
parent
commit
8b23e59453
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 246 additions and 231 deletions
  1. +2
    -6
      IPA.Tests/ProgramTest.cs
  2. +0
    -4
      IPA.Tests/ShortcutTest.cs
  3. +4
    -7
      IPA/PatchContext.cs
  4. +3
    -7
      IPA/Patcher/BackupManager.cs
  5. +15
    -13
      IPA/Patcher/BackupUnit.cs
  6. +13
    -12
      IPA/Patcher/Patcher.cs
  7. +15
    -12
      IPA/Patcher/Virtualizer.cs
  8. +33
    -27
      IPA/Program.cs
  9. +2
    -2
      IPA/Shortcut.cs
  10. +8
    -10
      IllusionInjector/Bootstrapper.cs
  11. +5
    -7
      IllusionInjector/CompositePlugin.cs
  12. +62
    -64
      IllusionInjector/ConsoleWindow.cs
  13. +1
    -3
      IllusionInjector/Injector.cs
  14. +10
    -13
      IllusionInjector/PluginComponent.cs
  15. +49
    -13
      IllusionInjector/PluginManager.cs
  16. +1
    -5
      IllusionPlugin/IEnhancedPlugin.cs
  17. +1
    -5
      IllusionPlugin/IPlugin.cs
  18. +1
    -3
      IllusionPlugin/IniFile.cs
  19. +3
    -4
      IllusionPlugin/ModPrefs.cs
  20. +18
    -14
      Launcher/Program.cs

+ 2
- 6
IPA.Tests/ProgramTest.cs View File

@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace IPA.Tests
@@ -26,7 +22,7 @@ namespace IPA.Tests

// Not-flat -> Not-Flat
[InlineData("native/x86/from.dll", "native/x86/to.dll", "native", false, new string[] { "native/x86/to.dll" })]
[InlineData("native/x86_64/from.dll", "native/x86_64/to.dll", "native", false, new string[] { "native/x86_64/to.dll" })]
[InlineData("native/x86_64/from.dll", "native/x86_64/to.dll", "native", false, new string[] { "native/x86_64/to.dll" })]

public void CopiesCorrectly(string from, string to, string nativeFolder, bool isFlat, string[] expected)
{


+ 0
- 4
IPA.Tests/ShortcutTest.cs View File

@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace IPA.Tests


+ 4
- 7
IPA/PatchContext.cs View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace IPA
{
@@ -37,7 +34,7 @@ namespace IPA
public static PatchContext Create(String[] args)
{
var context = new PatchContext();
context.Args = args;
context.Executable = args[0];
context.ProjectRoot = new FileInfo(context.Executable).Directory.FullName;
@@ -49,7 +46,7 @@ namespace IPA
context.ProjectName = Path.GetFileNameWithoutExtension(context.Executable);
context.DataPathDst = Path.Combine(context.ProjectRoot, context.ProjectName + "_Data");
context.ManagedPath = Path.Combine(context.DataPathDst, "Managed");
context.EngineFile = DetermineEngineFile(context.ManagedPath, "UnityEngine.CoreModule.dll", "UnityEngine.dll");
context.EngineFile = DetermineEngineFile(context.ManagedPath, "UnityEngine.CoreModule.dll", "UnityEngine.dll");
context.AssemblyFile = Path.Combine(context.ManagedPath, "Assembly-Csharp.dll");
context.BackupPath = Path.Combine(Path.Combine(context.IPARoot, "Backups"), context.ProjectName);
context.ShortcutPath = Path.Combine(context.ProjectRoot, $"{context.ProjectName} (Patch & Launch)") + ".lnk";
@@ -61,10 +58,10 @@ namespace IPA

private static string DetermineEngineFile(string basePath, params string[] candidates)
{
foreach(var candidate in candidates)
foreach (var candidate in candidates)
{
var fullPath = Path.Combine(basePath, candidate);
if(File.Exists(fullPath))
if (File.Exists(fullPath))
{
return fullPath;
}


+ 3
- 7
IPA/Patcher/BackupManager.cs View File

@@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace IPA.Patcher
{
@@ -22,11 +18,11 @@ namespace IPA.Patcher
{
return FindLatestBackup(context) != null;
}
public static bool Restore(PatchContext context)
{
var backup = FindLatestBackup(context);
if(backup != null)
if (backup != null)
{
backup.Restore();
backup.Delete();


+ 15
- 13
IPA/Patcher/BackupUnit.cs View File

@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;

namespace IPA.Patcher
{
@@ -30,13 +27,14 @@ namespace IPA.Patcher
_Context = context;
_BackupPath = new DirectoryInfo(Path.Combine(_Context.BackupPath, Name));
}
public static BackupUnit FromDirectory(DirectoryInfo directory, PatchContext context)
{
var unit = new BackupUnit(context, directory.Name);

// Parse directory
foreach(var file in directory.GetFiles("*", SearchOption.AllDirectories)) {
foreach (var file in directory.GetFiles("*", SearchOption.AllDirectories))
{
var relativePath = file.FullName.Substring(directory.FullName.Length + 1);
unit._Files.Add(relativePath);
}
@@ -60,7 +58,7 @@ namespace IPA.Patcher
/// <param name="path"></param>
public void Add(FileInfo file)
{
if(!file.FullName.StartsWith(_Context.ProjectRoot))
if (!file.FullName.StartsWith(_Context.ProjectRoot))
{
Console.Error.WriteLine("Invalid file path for backup! {0}", file);
return;
@@ -68,8 +66,8 @@ namespace IPA.Patcher

var relativePath = file.FullName.Substring(_Context.ProjectRoot.Length + 1);
var backupPath = new FileInfo(Path.Combine(_BackupPath.FullName, relativePath));
if(_Files.Contains(relativePath))
if (_Files.Contains(relativePath))
{
Console.WriteLine("Skipping backup of {0}", relativePath);
return;
@@ -81,7 +79,8 @@ namespace IPA.Patcher
if (file.Exists)
{
file.CopyTo(backupPath.FullName);
} else
}
else
{
// Make empty file
backupPath.Create().Close();
@@ -96,7 +95,7 @@ namespace IPA.Patcher
/// </summary>
public void Restore()
{
foreach(var relativePath in _Files)
foreach (var relativePath in _Files)
{
Console.WriteLine("Restoring {0}", relativePath);
// Original version
@@ -110,15 +109,18 @@ namespace IPA.Patcher
Console.WriteLine(" {0} => {1}", backupFile.FullName, target.FullName);
target.Directory.Create();
backupFile.CopyTo(target.FullName, true);
} else
}
else
{
Console.WriteLine(" x {0}", target.FullName);
if(target.Exists)
if (target.Exists)
{
target.Delete();
}
}
} else {
}
else
{
Console.Error.WriteLine("Backup not found!");
}
}


+ 13
- 12
IPA/Patcher/Patcher.cs View File

@@ -1,14 +1,13 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace IPA.Patcher
{
class PatchedModule
internal class PatchedModule
{
private static readonly string[] ENTRY_TYPES = { "Input", "Display" };

@@ -36,7 +35,7 @@ namespace IPA.Patcher
{
AssemblyResolver = resolver,
};
_Module = ModuleDefinition.ReadModule(_File.FullName, parameters);
}

@@ -46,7 +45,8 @@ namespace IPA.Patcher
{
foreach (var @ref in _Module.AssemblyReferences)
{
if (@ref.Name == "IllusionInjector") return true;
if (@ref.Name == "IllusionInjector")
return true;
}
return false;
}
@@ -61,18 +61,19 @@ namespace IPA.Patcher

_Module.AssemblyReferences.Add(nameReference);
int patched = 0;
foreach(var type in FindEntryTypes())
foreach (var type in FindEntryTypes())
{
if(PatchType(type, injector))
if (PatchType(type, injector))
{
patched++;
}
}
if(patched > 0)
if (patched > 0)
{
_Module.Write(_File.FullName);
} else
}
else
{
throw new Exception("Could not find any entry type!");
}


+ 15
- 12
IPA/Patcher/Virtualizer.cs View File

@@ -1,13 +1,11 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Text;
using Mono.Cecil;

namespace IPA.Patcher
{
class VirtualizedModule
internal class VirtualizedModule
{
private const string ENTRY_TYPE = "Display";

@@ -38,7 +36,7 @@ namespace IPA.Patcher

_Module = ModuleDefinition.ReadModule(_File.FullName, parameters);
}
/// <summary>
///
/// </summary>
@@ -55,17 +53,20 @@ namespace IPA.Patcher

private void VirtualizeType(TypeDefinition type)
{
if(type.IsSealed)
if (type.IsSealed)
{
// Unseal
type.IsSealed = false;
}

if (type.IsInterface) return;
if (type.IsAbstract) return;
if (type.IsInterface)
return;
if (type.IsAbstract)
return;

// These two don't seem to work.
if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
if (type.Name == "SceneControl" || type.Name == "ConfigUI")
return;

Console.WriteLine("Virtualizing {0}", type.Name);
// Take care of sub types
@@ -97,7 +98,8 @@ namespace IPA.Patcher

foreach (var field in type.Fields)
{
if (field.IsPrivate) field.IsFamily = true;
if (field.IsPrivate)
field.IsFamily = true;
}
}

@@ -106,7 +108,8 @@ namespace IPA.Patcher
get
{
var awakeMethods = _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake"));
if (awakeMethods.Count() == 0) return false;
if (awakeMethods.Count() == 0)
return false;

return ((float)awakeMethods.Count(m => m.IsVirtual) / awakeMethods.Count()) > 0.5f;
}


+ 33
- 27
IPA/Program.cs View File

@@ -1,29 +1,28 @@
using IPA.Patcher;
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using IPA.Patcher;

namespace IPA
{
public class Program
{
public enum Architecture {
public enum Architecture
{
x86,
x64,
Unknown
}

static void Main(string[] args)
private static void Main(string[] args)
{
if(args.Length < 1 || !args[0].EndsWith(".exe"))
if (args.Length < 1 || !args[0].EndsWith(".exe"))
{
Fail("Drag an (executable) file on the exe!");
}
@@ -44,7 +43,8 @@ namespace IPA
Install(context);
StartIfNeedBe(context);
}
} catch(Exception e)
}
catch (Exception e)
{
Fail(e.Message);
}
@@ -52,7 +52,8 @@ namespace IPA

private static void Validate(PatchContext c)
{
if (!File.Exists(c.LauncherPathSrc)) Fail("Couldn't find DLLs! Make sure you extracted all contents of the release archive.");
if (!File.Exists(c.LauncherPathSrc))
Fail("Couldn't find DLLs! Make sure you extracted all contents of the release archive.");
if (!Directory.Exists(c.DataPathDst) || !File.Exists(c.EngineFile))
{
Fail("Game does not seem to be a Unity project. Could not find the libraries to patch.");
@@ -74,8 +75,8 @@ namespace IPA

Console.WriteLine("Architecture: {0}", architecture);

CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup,
(from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture) );
CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup,
(from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture));

Console.WriteLine("Successfully updated files!");

@@ -109,9 +110,9 @@ namespace IPA
}

// Creating shortcut
if(!File.Exists(context.ShortcutPath))
if (!File.Exists(context.ShortcutPath))
{
Console.Write("Creating shortcut to IPA ({0})... ", context.IPA);
Console.Write("Creating shortcut to IPA ({0})... ", context.IPA);
try
{
Shortcut.Create(
@@ -124,7 +125,8 @@ namespace IPA
iconPath: context.Executable
);
Console.WriteLine("Created");
} catch (Exception e)
}
catch (Exception e)
{
Console.Error.WriteLine("Failed to create shortcut, but game was patched!");
}
@@ -145,15 +147,16 @@ namespace IPA
private static void Revert(PatchContext context)
{
Console.Write("Restoring backup... ");
if(BackupManager.Restore(context))
if (BackupManager.Restore(context))
{
Console.WriteLine("Done!");
} else
}
else
{
Console.WriteLine("Already vanilla!");
}

if (File.Exists(context.ShortcutPath))
{
Console.WriteLine("Deleting shortcut...");
@@ -177,7 +180,7 @@ namespace IPA

argList.RemoveAt(0);

if(launch)
if (launch)
{
Process.Start(context.Executable, Args(argList.ToArray()));
}
@@ -199,11 +202,13 @@ namespace IPA
// 32 bit
yield return new FileInfo(Path.Combine(nativePluginFolder.FullName, relevantBit.Substring("x86".Length + 1)));
}
else if(is64Bit && (preferredArchitecture == Architecture.x64 || preferredArchitecture == Architecture.Unknown))
else if (is64Bit && (preferredArchitecture == Architecture.x64 || preferredArchitecture == Architecture.Unknown))
{
// 64 bit
yield return new FileInfo(Path.Combine(nativePluginFolder.FullName, relevantBit.Substring("x86_64".Length + 1)));
} else {
}
else
{
// Throw away
yield break;
}
@@ -231,7 +236,7 @@ namespace IPA

public static void CopyAll(DirectoryInfo source, DirectoryInfo target, bool aggressive, BackupUnit backup, Func<FileInfo, FileInfo, IEnumerable<FileInfo>> interceptor = null)
{
if(interceptor == null)
if (interceptor == null)
{
interceptor = PassThroughInterceptor;
}
@@ -239,7 +244,8 @@ namespace IPA
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
foreach(var targetFile in interceptor(fi, new FileInfo(Path.Combine(target.FullName, fi.Name)))) {
foreach (var targetFile in interceptor(fi, new FileInfo(Path.Combine(target.FullName, fi.Name))))
{
if (!targetFile.Exists || targetFile.LastWriteTimeUtc < fi.LastWriteTimeUtc || aggressive)
{
targetFile.Directory.Create();
@@ -259,8 +265,7 @@ namespace IPA
}
}


static void Fail(string message)
private static void Fail(string message)
{
Console.Error.Write("ERROR: " + message);
if (!Environment.CommandLine.Contains("--nowait"))
@@ -296,7 +301,7 @@ namespace IPA
using (var reader = new BinaryReader(File.OpenRead(assembly)))
{
var header = reader.ReadUInt16();
if(header == 0x5a4d)
if (header == 0x5a4d)
{
reader.BaseStream.Seek(60, SeekOrigin.Begin); // this location contains the offset for the PE header
var peOffset = reader.ReadUInt32();
@@ -312,7 +317,8 @@ namespace IPA
return Architecture.x64;
else
return Architecture.Unknown;
} else
}
else
{
// Not a supported binary
return Architecture.Unknown;


+ 2
- 2
IPA/Shortcut.cs View File

@@ -3,10 +3,10 @@ using System.Runtime.InteropServices;

namespace IPA
{
public class Shortcut
public static class Shortcut
{
private static Type m_type = Type.GetTypeFromProgID("WScript.Shell");
private static object m_shell = Activator.CreateInstance(m_type);
private static readonly object m_shell = Activator.CreateInstance(m_type);

[ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
private interface IWshShortcut


+ 8
- 10
IllusionInjector/Bootstrapper.cs View File

@@ -1,28 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace IllusionInjector
{
class Bootstrapper : MonoBehaviour
internal class Bootstrapper : MonoBehaviour
{
public event Action Destroyed = delegate {};
void Awake()
public event Action Destroyed = delegate { };
private void Awake()
{
if (Environment.CommandLine.Contains("--verbose") && !Screen.fullScreen)
if (Environment.CommandLine.Contains("--verbose") && (!Screen.fullScreen || Environment.CommandLine.Contains("--ipa-console")))
{
Windows.GuiConsole.CreateConsole();
}
}

void Start()
private void Start()
{
Destroy(gameObject);
}
void OnDestroy()

private void OnDestroy()
{
Destroyed();
}


+ 5
- 7
IllusionInjector/CompositePlugin.cs View File

@@ -1,20 +1,18 @@
using IllusionPlugin;
using System;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using IllusionPlugin;

namespace IllusionInjector
{
public class CompositePlugin : IPlugin
{
IEnumerable<IPlugin> plugins;
private readonly IEnumerable<IPlugin> plugins;

private delegate void CompositeCall(IPlugin plugin);

public CompositePlugin(IEnumerable<IPlugin> plugins)
{
this.plugins = plugins;
this.plugins = plugins;
}

public void OnApplicationStart()
@@ -24,7 +22,7 @@ namespace IllusionInjector

public void OnApplicationQuit()
{
Invoke(plugin => plugin.OnApplicationQuit());
Invoke(plugin => plugin.OnApplicationQuit());
}

public void OnLevelWasLoaded(int level)


+ 62
- 64
IllusionInjector/ConsoleWindow.cs View File

@@ -1,71 +1,69 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace Windows
{

class GuiConsole
{
public static void CreateConsole()
{
if (hasConsole)
return;
if (oldOut == IntPtr.Zero)
oldOut = GetStdHandle( -11 );
if (! AllocConsole())
throw new Exception("AllocConsole() failed");
conOut = CreateFile( "CONOUT$", 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero );
if (! SetStdHandle(-11, conOut))
throw new Exception("SetStdHandle() failed");
StreamToConsole();
hasConsole = true;
}
public static void ReleaseConsole()
{
if (! hasConsole)
return;
if (! CloseHandle(conOut))
throw new Exception("CloseHandle() failed");
conOut = IntPtr.Zero;
if (! FreeConsole())
throw new Exception("FreeConsole() failed");
if (! SetStdHandle(-11, oldOut))
throw new Exception("SetStdHandle() failed");
StreamToConsole();
hasConsole = false;
}
private static void StreamToConsole()
{
Stream cstm = Console.OpenStandardOutput();
StreamWriter cstw = new StreamWriter( cstm, Encoding.Default );
cstw.AutoFlush = true;
Console.SetOut( cstw );
Console.SetError( cstw );
}
private static bool hasConsole = false;
private static IntPtr conOut;
private static IntPtr oldOut;
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError=false)]
private static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr GetStdHandle( int nStdHandle );
[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern IntPtr CreateFile(
string fileName,
int desiredAccess,
int shareMode,
IntPtr securityAttributes,
int creationDisposition,
int flagsAndAttributes,
IntPtr templateFile );
[DllImport("kernel32.dll", ExactSpelling=true, SetLastError=true)]
private static extern bool CloseHandle(IntPtr handle);
}
internal class GuiConsole
{
public static void CreateConsole()
{
if (hasConsole)
return;
if (oldOut == IntPtr.Zero)
oldOut = GetStdHandle(-11);
if (!AllocConsole())
throw new Exception("AllocConsole() failed");
conOut = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, 3, 0, IntPtr.Zero);
if (!SetStdHandle(-11, conOut))
throw new Exception("SetStdHandle() failed");
StreamToConsole();
hasConsole = true;
}
public static void ReleaseConsole()
{
if (!hasConsole)
return;
if (!CloseHandle(conOut))
throw new Exception("CloseHandle() failed");
conOut = IntPtr.Zero;
if (!FreeConsole())
throw new Exception("FreeConsole() failed");
if (!SetStdHandle(-11, oldOut))
throw new Exception("SetStdHandle() failed");
StreamToConsole();
hasConsole = false;
}
private static void StreamToConsole()
{
Stream cstm = Console.OpenStandardOutput();
StreamWriter cstw = new StreamWriter(cstm, Encoding.Default);
cstw.AutoFlush = true;
Console.SetOut(cstw);
Console.SetError(cstw);
}
private static bool hasConsole = false;
private static IntPtr conOut;
private static IntPtr oldOut;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = false)]
private static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetStdHandle(int nStdHandle, IntPtr hConsoleOutput);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile(
string fileName,
int desiredAccess,
int shareMode,
IntPtr securityAttributes,
int creationDisposition,
int flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool CloseHandle(IntPtr handle);
}
}

+ 1
- 3
IllusionInjector/Injector.cs View File

@@ -1,6 +1,4 @@
using System;
using System.IO;
using UnityEngine;
using UnityEngine;

namespace IllusionInjector
{


+ 10
- 13
IllusionInjector/PluginComponent.cs View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine;

namespace IllusionInjector
{
@@ -16,7 +13,7 @@ namespace IllusionInjector
return new GameObject("IPA_PluginManager").AddComponent<PluginComponent>();
}

void Awake()
private void Awake()
{
DontDestroyOnLoad(gameObject);

@@ -24,12 +21,12 @@ namespace IllusionInjector
plugins.OnApplicationStart();
}

void Start()
private void Start()
{
OnLevelWasLoaded(Application.loadedLevel);
}

void Update()
private void Update()
{
if (freshlyLoaded)
{
@@ -39,32 +36,32 @@ namespace IllusionInjector
plugins.OnUpdate();
}

void LateUpdate()
private void LateUpdate()
{
plugins.OnLateUpdate();
}

void FixedUpdate()
private void FixedUpdate()
{
plugins.OnFixedUpdate();
}

void OnDestroy()
private void OnDestroy()
{
if (!quitting)
{
Create();
}
}
void OnApplicationQuit()
private void OnApplicationQuit()
{
plugins.OnApplicationQuit();

quitting = true;
}

void OnLevelWasLoaded(int level)
private void OnLevelWasLoaded(int level)
{
plugins.OnLevelWasLoaded(level);
freshlyLoaded = true;


+ 49
- 13
IllusionInjector/PluginManager.cs View File

@@ -1,13 +1,11 @@
using IllusionPlugin;
using System;
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;
using IllusionPlugin;

namespace IllusionInjector
{
@@ -22,7 +20,7 @@ namespace IllusionInjector
{
get
{
if(_Plugins == null)
if (_Plugins == null)
{
LoadPlugins();
}
@@ -41,17 +39,18 @@ namespace IllusionInjector
Console.WriteLine(exeName);
_Plugins = new List<IPlugin>();

if (!Directory.Exists(pluginDirectory)) return;
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("Running on Unity {0} using {1}", UnityEngine.Application.unityVersion, GetFrameworkVersion());
Console.WriteLine("-----------------------------");
Console.WriteLine("Loading plugins from {0} and found {1}", pluginDirectory, _Plugins.Count);
Console.WriteLine("-----------------------------");
@@ -76,11 +75,10 @@ namespace IllusionInjector

foreach (Type t in assembly.GetTypes())
{
if (t.GetInterface("IPlugin") != null)
if (IsValidPlugin(t))
{
try
{

IPlugin pluginInstance = Activator.CreateInstance(t) as IPlugin;
string[] filter = null;

@@ -88,8 +86,8 @@ namespace IllusionInjector
{
filter = ((IEnhancedPlugin)pluginInstance).Filter;
}
if(filter == null || Enumerable.Contains(filter, exeName, StringComparer.OrdinalIgnoreCase))
if (filter == null || Enumerable.Contains(filter, exeName, StringComparer.OrdinalIgnoreCase))
plugins.Add(pluginInstance);
}
catch (Exception e)
@@ -108,6 +106,44 @@ namespace IllusionInjector
return plugins;
}

private static bool IsValidPlugin(Type type)
{
return typeof(IPlugin).IsAssignableFrom(type)
&& !type.IsAbstract
&& !type.IsInterface
&& type.GetConstructor(Type.EmptyTypes) != null;
}

private static string GetFrameworkVersion()
{
var version = Environment.Version.ToString();

try
{
switch (version)
{
case "2.0.50727.1433":
return ".NET 3.5 Equivalent";
case "4.0.30319.17020":
// For reasons unknown, switching to netstandard seems to set this back to .NET 4.0
var netstandard = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == "netstandard");
if (netstandard != null)
return $".NET Standard {netstandard.GetName().Version.ToString(2)}";

goto default;
case "4.0.30319.42000":
return ".NET 4.x";
default:
return $".NET Framework {version}";
}
}
catch
{
// In case something goes wrong, return the best we can guess
return version;
}
}

public class AppInfo
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)]


+ 1
- 5
IllusionPlugin/IEnhancedPlugin.cs View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace IllusionPlugin
namespace IllusionPlugin
{
public interface IEnhancedPlugin : IPlugin
{


+ 1
- 5
IllusionPlugin/IPlugin.cs View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace IllusionPlugin
namespace IllusionPlugin
{
/// <summary>
/// Interface for generic Illusion unity plugins. Every class that implements this will be loaded if the DLL is placed at


+ 1
- 3
IllusionPlugin/IniFile.cs View File

@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;



+ 3
- 4
IllusionPlugin/ModPrefs.cs View File

@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace IllusionPlugin
{
@@ -58,7 +56,7 @@ namespace IllusionPlugin
return value;
else if (autoSave)
SetInt(section, name, defaultValue);
return defaultValue;
}

@@ -96,7 +94,8 @@ namespace IllusionPlugin
if (sVal == "1" || sVal == "0")
{
return sVal == "1";
} else if (autoSave)
}
else if (autoSave)
{
SetBool(section, name, defaultValue);
}


+ 18
- 14
Launcher/Program.cs View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -8,41 +7,43 @@ using System.Windows.Forms;

namespace Launcher
{
static class Program
internal static class Program
{
private static string[] TABOO_NAMES = {
private static readonly string[] TABOO_NAMES = {
//"Start",
//"Update",
//"Awake",
//"OnDestroy"
};
private static string[] ENTRY_TYPES = { "Display" };
private static readonly string[] ENTRY_TYPES = { "Display" };
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
private static void Main()
{
try {
try
{
var execPath = Application.ExecutablePath;
var fileName = Path.GetFileNameWithoutExtension(execPath);
if (fileName.IndexOf("VR") == -1 && fileName.IndexOf("_") == -1)
{
Fail("File not named correctly!");
}
bool vrMode = fileName.IndexOf("VR") > 0;
string baseName = execPath.Substring(0, vrMode
? execPath.LastIndexOf("VR")
: execPath.LastIndexOf("_"));
string executable = baseName + ".exe";
var file = new FileInfo(executable);
if (file.Exists)
{
var args = Environment.GetCommandLineArgs().ToList();
if (vrMode) args.Add("--vr");
if (vrMode)
args.Add("--vr");
EnsureIPA(executable);
StartGame(executable, args.ToArray());
}
@@ -50,10 +51,12 @@ namespace Launcher
{
MessageBox.Show("Could not find: " + file.FullName, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch(Exception globalException) {
}
catch (Exception globalException)
{
MessageBox.Show(globalException.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

private static void EnsureIPA(string executable)
@@ -65,7 +68,7 @@ namespace Launcher

var process = Process.Start(processStart);
process.WaitForExit();
if(process.ExitCode != 0)
if (process.ExitCode != 0)
{
Fail(process.StandardError.ReadToEnd());
}
@@ -77,7 +80,8 @@ namespace Launcher
Process.Start(executable, arguments);
}

private static void Fail(string reason) {
private static void Fail(string reason)
{
throw new Exception(reason);
}



Loading…
Cancel
Save