Browse Source

Add files via upload

refactor
Michael Guedko 6 years ago
committed by GitHub
parent
commit
2d13f902ba
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2416 additions and 21 deletions
  1. +93
    -0
      IPA.Tests/IPA.Tests.csproj
  2. +39
    -0
      IPA.Tests/ProgramTest.cs
  3. +36
    -0
      IPA.Tests/Properties/AssemblyInfo.cs
  4. +37
    -0
      IPA.Tests/ShortcutTest.cs
  5. +11
    -0
      IPA.Tests/packages.config
  6. +99
    -0
      IPA/IPA.csproj
  7. +63
    -0
      IPA/PatchContext.cs
  8. +39
    -0
      IPA/Patcher/BackupManager.cs
  9. +128
    -0
      IPA/Patcher/BackupUnit.cs
  10. +99
    -0
      IPA/Patcher/Patcher.cs
  11. +115
    -0
      IPA/Patcher/Virtualizer.cs
  12. +365
    -0
      IPA/Program.cs
  13. +36
    -0
      IPA/Properties/AssemblyInfo.cs
  14. +61
    -0
      IPA/Shortcut.cs
  15. BIN
      IPA/favicon.ico
  16. +1
    -0
      IPA/obj/Debug/IPA.csproj.CoreCompileInputs.cache
  17. +4
    -0
      IPA/packages.config
  18. +30
    -0
      IllusionInjector/Bootstrapper.cs
  19. +109
    -0
      IllusionInjector/CompositePlugin.cs
  20. +71
    -0
      IllusionInjector/ConsoleWindow.cs
  21. +66
    -0
      IllusionInjector/IllusionInjector.csproj
  22. +25
    -0
      IllusionInjector/Injector.cs
  23. +74
    -0
      IllusionInjector/PluginComponent.cs
  24. +128
    -0
      IllusionInjector/PluginManager.cs
  25. +36
    -0
      IllusionInjector/Properties/AssemblyInfo.cs
  26. +1
    -0
      IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache
  27. +21
    -21
      LICENSE
  28. +91
    -0
      Launcher/Launcher.csproj
  29. +100
    -0
      Launcher/Program.cs
  30. +36
    -0
      Launcher/Properties/AssemblyInfo.cs
  31. +63
    -0
      Launcher/Properties/Resources.Designer.cs
  32. +117
    -0
      Launcher/Properties/Resources.resx
  33. +26
    -0
      Launcher/Properties/Settings.Designer.cs
  34. +7
    -0
      Launcher/Properties/Settings.settings
  35. +63
    -0
      Launcher/Resources.Designer.cs
  36. +121
    -0
      Launcher/Resources.resx
  37. +1
    -0
      Launcher/obj/Debug/Launcher.csproj.CoreCompileInputs.cache
  38. +4
    -0
      Launcher/packages.config
  39. BIN
      Launcher/syringe.ico
  40. BIN
      Libs/UnityEngine.dll

+ 93
- 0
IPA.Tests/IPA.Tests.csproj View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C66092B0-5C1E-44E9-B524-E0E8E1425379}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IPA.Tests</RootNamespace>
<AssemblyName>IPA.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ProgramTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ShortcutTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IPA\IPA.csproj">
<Project>{14092533-98bb-40a4-9afc-27bb75672a70}</Project>
<Name>IPA</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 39
- 0
IPA.Tests/ProgramTest.cs View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace IPA.Tests
{
public class ProgramTest
{
[Theory]
// Unrelated path
[InlineData("test/from.dll", "test/to.dll", "native", false, new string[] { "test/to.dll" })]
// Flat -> Not-Flat
[InlineData("native/from.dll", "native/to.dll", "native", false, new string[] { "native/x86/to.dll", "native/x86_64/to.dll" })]
// Flat -> Flat
[InlineData("native/from.dll", "native/to.dll", "native", true, new string[] { "native/to.dll" })]
// Not-Flat -> Flat
[InlineData("native/x86/from.dll", "native/x86/to.dll", "native", true, new string[] { })]
[InlineData("native/x86_64/from.dll", "native/x86_64/to.dll", "native", true, new string[] { "native/to.dll" })]
// 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" })]
public void CopiesCorrectly(string from, string to, string nativeFolder, bool isFlat, string[] expected)
{
var outcome = Program.NativePluginInterceptor(new FileInfo(from), new FileInfo(to), new DirectoryInfo(nativeFolder), isFlat).Select(f => f.FullName).ToList();
var expectedPaths = expected.Select(e => new FileInfo(e)).Select(f => f.FullName).ToList();
Assert.Equal(expectedPaths, outcome);
}
}
}

+ 36
- 0
IPA.Tests/Properties/AssemblyInfo.cs View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("IPA.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("IPA.Tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c66092b0-5c1e-44e9-b524-e0e8e1425379")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

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

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace IPA.Tests
{
public class ShortcutTest
{
[Fact]
public void CanDealWithEmptyFiles()
{
Shortcut.Create(".lnk", "", "", "", "", "", "");
}
[Fact]
public void CanDealWithLongFiles()
{
Shortcut.Create(".lnk", Path.Combine(Path.GetTempPath(), string.Join("_", new string[500])), "", "", "", "", "");
}
[Fact]
public void CantDealWithNull()
{
Assert.Throws<ArgumentException>(() => Shortcut.Create(".lnk", null, "", "", "", "", ""));
}
[Fact]
public void CanDealWithWeirdCharacters()
{
Shortcut.Create(".lnk", "äöü", "", "", "", "", "");
}
}
}

+ 11
- 0
IPA.Tests/packages.config View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="xunit" version="2.1.0" targetFramework="net452" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net452" />
<package id="xunit.assert" version="2.1.0" targetFramework="net452" />
<package id="xunit.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net452" />
<package id="xunit.runner.console" version="2.1.0" targetFramework="net452" />
<package id="xunit.runner.visualstudio" version="2.1.0" targetFramework="net452" />
</packages>

+ 99
- 0
IPA/IPA.csproj View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{14092533-98BB-40A4-9AFC-27BB75672A70}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IPA</RootNamespace>
<AssemblyName>IPA</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net35\Mono.Cecil.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net35\Mono.Cecil.Mdb.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net35\Mono.Cecil.Pdb.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<HintPath>..\packages\Mono.Cecil.0.9.6.4\lib\net35\Mono.Cecil.Rocks.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PatchContext.cs" />
<Compile Include="Patcher\BackupManager.cs" />
<Compile Include="Patcher\BackupUnit.cs" />
<Compile Include="Patcher\Patcher.cs" />
<Compile Include="Patcher\Virtualizer.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Shortcut.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico" />
</ItemGroup>
<ItemGroup>
<Folder Include="IPA\Fallback\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<Target Name="AfterBuild">
<Message Text="Packing..." Importance="normal" />
<ItemGroup>
<Launcher Include="$(SolutionDir)Launcher\$(OutDir)Launcher.exe" />
<Dlls Include="$(SolutionDir)IllusionInjector\$(OutDir)**\*" />
</ItemGroup>
<Copy SourceFiles="@(Dlls)" DestinationFolder="$(OutputPath)IPA\Data\Managed" />
<Copy SourceFiles="@(Launcher)" DestinationFolder="$(OutputPath)IPA" />
</Target>
</Project>

+ 63
- 0
IPA/PatchContext.cs View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace IPA
{
public class PatchContext
{
/// <summary>
/// Gets the filename of the executable.
/// </summary>
public string Executable { get; private set; }
/// <summary>
/// Gets the path to the launcher executable (in the IPA folder)
/// </summary>
public string LauncherPathSrc { get; private set; }
public string DataPathSrc { get; private set; }
public string PluginsFolder { get; private set; }
public string ProjectName { get; private set; }
public string DataPathDst { get; private set; }
public string ManagedPath { get; private set; }
public string EngineFile { get; private set; }
public string AssemblyFile { get; private set; }
public string[] Args { get; private set; }
public string ProjectRoot { get; private set; }
public string IPARoot { get; private set; }
public string ShortcutPath { get; private set; }
public string IPA { get; private set; }
public string BackupPath { get; private set; }
private PatchContext() { }
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;
context.IPARoot = Path.Combine(context.ProjectRoot, "IPA");
context.IPA = Assembly.GetExecutingAssembly().Location ?? Path.Combine(context.ProjectRoot, "IPA.exe");
context.LauncherPathSrc = Path.Combine(context.IPARoot, "Launcher.exe");
context.DataPathSrc = Path.Combine(context.IPARoot, "Data");
context.PluginsFolder = Path.Combine(context.ProjectRoot, "Plugins");
context.ProjectName = Path.GetFileNameWithoutExtension(context.Executable);
context.DataPathDst = Path.Combine(context.ProjectRoot, context.ProjectName + "_Data");
context.ManagedPath = Path.Combine(context.DataPathDst, "Managed");
context.EngineFile = Path.Combine(context.ManagedPath, "UnityEngineCore.dll");
context.AssemblyFile = Path.Combine(context.ManagedPath, "Assembly-CSharp.dll");
context.BackupPath = Path.Combine(Path.Combine(context.IPARoot, "Backups"), context.ProjectName);
string shortcutName = string.Format("{0} (Patch & Launch)", context.ProjectName);
context.ShortcutPath = Path.Combine(context.ProjectRoot, shortcutName) + ".lnk";
Directory.CreateDirectory(context.BackupPath);
return context;
}
}
}

+ 39
- 0
IPA/Patcher/BackupManager.cs View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace IPA.Patcher
{
public class BackupManager
{
public static BackupUnit FindLatestBackup(PatchContext context)
{
return new DirectoryInfo(context.BackupPath)
.GetDirectories()
.OrderByDescending(p => p.Name)
.Select(p => BackupUnit.FromDirectory(p, context))
.FirstOrDefault();
}
public static bool HasBackup(PatchContext context)
{
return FindLatestBackup(context) != null;
}
public static bool Restore(PatchContext context)
{
var backup = FindLatestBackup(context);
if(backup != null)
{
backup.Restore();
backup.Delete();
return true;
}
return false;
}
}
}

+ 128
- 0
IPA/Patcher/BackupUnit.cs View File

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
namespace IPA.Patcher
{
/// <summary>
/// A unit for backup. WIP.
/// </summary>
public class BackupUnit
{
public string Name { get; private set; }
private DirectoryInfo _BackupPath;
private PatchContext _Context;
private List<string> _Files = new List<string>();
public BackupUnit(PatchContext context) : this(context, DateTime.Now.ToString("yyyy-MM-dd_h-mm-ss"))
{
}
private BackupUnit(PatchContext context, string name)
{
Name = name;
_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)) {
var relativePath = file.FullName.Substring(directory.FullName.Length + 1);
unit._Files.Add(relativePath);
}
return unit;
}
public void Add(string file)
{
Add(new FileInfo(file));
}
internal void Delete()
{
_BackupPath.Delete(true);
}
/// <summary>
/// Adds a file to the list of changed files and backups it.
/// </summary>
/// <param name="path"></param>
public void Add(FileInfo file)
{
if(!file.FullName.StartsWith(_Context.ProjectRoot))
{
Console.Error.WriteLine("Invalid file path for backup! {0}", file);
return;
}
var relativePath = file.FullName.Substring(_Context.ProjectRoot.Length + 1);
var backupPath = new FileInfo(Path.Combine(_BackupPath.FullName, relativePath));
if(_Files.Contains(relativePath))
{
Console.WriteLine("Skipping backup of {0}", relativePath);
return;
}
// Copy over
backupPath.Directory.Create();
if (file.Exists)
{
file.CopyTo(backupPath.FullName);
} else
{
// Make empty file
backupPath.Create().Close();
}
// Add to list
_Files.Add(relativePath);
}
/// <summary>
/// Reverts the changes made in this unit.
/// </summary>
public void Restore()
{
foreach(var relativePath in _Files)
{
Console.WriteLine("Restoring {0}", relativePath);
// Original version
var backupFile = new FileInfo(Path.Combine(_BackupPath.FullName, relativePath));
var target = new FileInfo(Path.Combine(_Context.ProjectRoot, relativePath));
if (backupFile.Exists)
{
if (backupFile.Length > 0)
{
Console.WriteLine(" {0} => {1}", backupFile.FullName, target.FullName);
target.Directory.Create();
backupFile.CopyTo(target.FullName, true);
} else
{
Console.WriteLine(" x {0}", target.FullName);
if(target.Exists)
{
target.Delete();
}
}
} else {
Console.Error.WriteLine("Backup not found!");
}
}
}
}
}

+ 99
- 0
IPA/Patcher/Patcher.cs View File

@ -0,0 +1,99 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace IPA.Patcher
{
class PatchedModule
{
private static readonly string[] ENTRY_TYPES = { "Input", "Display" };
private FileInfo _File;
private ModuleDefinition _Module;
public static PatchedModule Load(string engineFile)
{
return new PatchedModule(engineFile);
}
private PatchedModule(string engineFile)
{
_File = new FileInfo(engineFile);
LoadModules();
}
private void LoadModules()
{
var resolver = new DefaultAssemblyResolver();
resolver.AddSearchDirectory(_File.DirectoryName);
var parameters = new ReaderParameters
{
AssemblyResolver = resolver,
};
_Module = ModuleDefinition.ReadModule(_File.FullName, parameters);
}
public bool IsPatched
{
get
{
foreach (var @ref in _Module.AssemblyReferences)
{
if (@ref.Name == "IllusionInjector") return true;
}
return false;
}
}
public void Patch()
{
// First, let's add the reference
var nameReference = new AssemblyNameReference("IllusionInjector", new Version(1, 0, 0, 0));
var injectorPath = Path.Combine(_File.DirectoryName, "IllusionInjector.dll");
var injector = ModuleDefinition.ReadModule(injectorPath);
_Module.AssemblyReferences.Add(nameReference);
int patched = 0;
foreach(var type in FindEntryTypes())
{
if(PatchType(type, injector))
{
patched++;
}
}
if(patched > 0)
{
_Module.Write(_File.FullName);
} else
{
throw new Exception("Could not find any entry type!");
}
}
private bool PatchType(TypeDefinition targetType, ModuleDefinition injector)
{
var targetMethod = targetType.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
if (targetMethod != null)
{
var methodReference = _Module.Import(injector.GetType("IllusionInjector.Injector").Methods.First(m => m.Name == "Inject"));
targetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, methodReference));
return true;
}
return false;
}
private IEnumerable<TypeDefinition> FindEntryTypes()
{
return _Module.GetTypes().Where(m => ENTRY_TYPES.Contains(m.Name));
}
}
}

+ 115
- 0
IPA/Patcher/Virtualizer.cs View File

@ -0,0 +1,115 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace IPA.Patcher
{
class VirtualizedModule
{
private const string ENTRY_TYPE = "Display";
private FileInfo _File;
private ModuleDefinition _Module;
public static VirtualizedModule Load(string engineFile)
{
return new VirtualizedModule(engineFile);
}
private VirtualizedModule(string assemblyFile)
{
_File = new FileInfo(assemblyFile);
LoadModules();
}
private void LoadModules()
{
var resolver = new DefaultAssemblyResolver();
resolver.AddSearchDirectory(_File.DirectoryName);
var parameters = new ReaderParameters
{
AssemblyResolver = resolver,
};
_Module = ModuleDefinition.ReadModule(_File.FullName, parameters);
}
/// <summary>
///
/// </summary>
/// <param name="module"></param>
public void Virtualize()
{
foreach (var type in _Module.Types)
{
VirtualizeType(type);
}
_Module.Write(_File.FullName);
}
private void VirtualizeType(TypeDefinition type)
{
if(type.IsSealed)
{
// Unseal
type.IsSealed = false;
}
if (type.IsInterface) return;
if (type.IsAbstract) return;
// These two don't seem to work.
if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
Console.WriteLine("Virtualizing {0}", type.Name);
// Take care of sub types
foreach (var subType in type.NestedTypes)
{
VirtualizeType(subType);
}
foreach (var method in type.Methods)
{
if (method.IsManaged
&& method.IsIL
&& !method.IsStatic
&& !method.IsVirtual
&& !method.IsAbstract
&& !method.IsAddOn
&& !method.IsConstructor
&& !method.IsSpecialName
&& !method.IsGenericInstance
&& !method.HasOverrides)
{
method.IsVirtual = true;
method.IsPublic = true;
method.IsPrivate = false;
method.IsNewSlot = true;
method.IsHideBySig = true;
}
}
foreach (var field in type.Fields)
{
if (field.IsPrivate) field.IsFamily = true;
}
}
public bool IsVirtualized
{
get
{
var awakeMethods = _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake"));
if (awakeMethods.Count() == 0) return false;
return ((float)awakeMethods.Count(m => m.IsVirtual) / awakeMethods.Count()) > 0.5f;
}
}
}
}

+ 365
- 0
IPA/Program.cs View File

@ -0,0 +1,365 @@
using IPA.Patcher;
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;
namespace IPA
{
public class Program
{
public enum Architecture {
x86,
x64,
Unknown
}
static void Main(string[] args)
{
if(args.Length < 1 || !args[0].EndsWith(".exe"))
{
Fail("Drag an (executable) file on the exe!");
}
try
{
var context = PatchContext.Create(args);
bool isRevert = args.Contains("--revert") || Keyboard.IsKeyDown(Keys.LMenu);
// Sanitizing
Validate(context);
if (isRevert)
{
Revert(context);
}
else
{
Install(context);
StartIfNeedBe(context);
}
} catch(Exception e)
{
Fail(e.Message);
}
}
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 (!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.");
}
}
private static void Install(PatchContext context)
{
try
{
var backup = new BackupUnit(context);
// Copying
Console.WriteLine("Updating files... ");
var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins");
bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll"));
bool force = !BackupManager.HasBackup(context) || context.Args.Contains("-f") || context.Args.Contains("--force");
var architecture = DetectArchitecture(context.Executable);
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) );
Console.WriteLine("Successfully updated files!");
if (!Directory.Exists(context.PluginsFolder))
{
Console.WriteLine("Creating plugins folder... ");
Directory.CreateDirectory(context.PluginsFolder);
}
// Patching
var patchedModule = PatchedModule.Load(context.EngineFile);
if (!patchedModule.IsPatched)
{
Console.Write("Patching UnityEngine.dll... ");
backup.Add(context.EngineFile);
patchedModule.Patch();
Console.WriteLine("Done!");
}
// Virtualizing
if (File.Exists(context.AssemblyFile))
{
var virtualizedModule = VirtualizedModule.Load(context.AssemblyFile);
if (!virtualizedModule.IsVirtualized)
{
Console.Write("Virtualizing Assembly-Csharp.dll... ");
backup.Add(context.AssemblyFile);
virtualizedModule.Virtualize();
Console.WriteLine("Done!");
}
}
// Creating shortcut
if(!File.Exists(context.ShortcutPath))
{
Console.Write("Creating shortcut to IPA ({0})... ", context.IPA);
try
{
Shortcut.Create(
fileName: context.ShortcutPath,
targetPath: context.IPA,
arguments: Args(context.Executable, "--launch"),
workingDirectory: context.ProjectRoot,
description: "Launches the game and makes sure it's in a patched state",
hotkey: "",
iconPath: context.Executable
);
Console.WriteLine("Created");
} catch (Exception e)
{
Console.Error.WriteLine("Failed to create shortcut, but game was patched!");
}
}
}
catch (Exception e)
{
Fail("Oops! This should not have happened.\n\n" + e);
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Finished!");
Console.ResetColor();
}
private static void Revert(PatchContext context)
{
Console.Write("Restoring backup... ");
if(BackupManager.Restore(context))
{
Console.WriteLine("Done!");
} else
{
Console.WriteLine("Already vanilla!");
}
if (File.Exists(context.ShortcutPath))
{
Console.WriteLine("Deleting shortcut...");
File.Delete(context.ShortcutPath);
}
Console.WriteLine("");
Console.WriteLine("--- Done reverting ---");
if (!Environment.CommandLine.Contains("--nowait"))
{
Console.WriteLine("\n\n[Press any key to quit]");
Console.ReadKey();
}
}
private static void StartIfNeedBe(PatchContext context)
{
var argList = context.Args.ToList();
bool launch = argList.Remove("--launch");
argList.RemoveAt(0);
if(launch)
{
Process.Start(context.Executable, Args(argList.ToArray()));
}
}
public static IEnumerable<FileInfo> NativePluginInterceptor(FileInfo from, FileInfo to, DirectoryInfo nativePluginFolder, bool isFlat, Architecture preferredArchitecture)
{
if (to.FullName.StartsWith(nativePluginFolder.FullName))
{
var relevantBit = to.FullName.Substring(nativePluginFolder.FullName.Length + 1);
// Goes into the plugin folder!
bool isFileFlat = !relevantBit.StartsWith("x86");
if (isFlat && !isFileFlat)
{
// Flatten structure
bool is64Bit = relevantBit.StartsWith("x86_64");
if (!is64Bit && preferredArchitecture == Architecture.x86)
{
// 32 bit
yield return new FileInfo(Path.Combine(nativePluginFolder.FullName, relevantBit.Substring("x86".Length + 1)));
}
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 {
// Throw away
yield break;
}
}
else if (!isFlat && isFileFlat)
{
// Deepen structure
yield return new FileInfo(Path.Combine(Path.Combine(nativePluginFolder.FullName, "x86"), relevantBit));
yield return new FileInfo(Path.Combine(Path.Combine(nativePluginFolder.FullName, "x86_64"), relevantBit));
}
else
{
yield return to;
}
}
else
{
yield return to;
}
}
private static IEnumerable<FileInfo> PassThroughInterceptor(FileInfo from, FileInfo to)
{
yield return to;
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target, bool aggressive, BackupUnit backup, Func<FileInfo, FileInfo, IEnumerable<FileInfo>> interceptor = null)
{
if(interceptor == null)
{
interceptor = PassThroughInterceptor;
}
// 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)))) {
if (!targetFile.Exists || targetFile.LastWriteTimeUtc < fi.LastWriteTimeUtc || aggressive)
{
targetFile.Directory.Create();
Console.WriteLine(@"Copying {0}", targetFile.FullName);
backup.Add(targetFile);
fi.CopyTo(targetFile.FullName, true);
}
}
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir = new DirectoryInfo(Path.Combine(target.FullName, diSourceSubDir.Name));
CopyAll(diSourceSubDir, nextTargetSubDir, aggressive, backup, interceptor);
}
}
static void Fail(string message)
{
Console.Error.Write("ERROR: " + message);
if (!Environment.CommandLine.Contains("--nowait"))
{
Console.WriteLine("\n\n[Press any key to quit]");
Console.ReadKey();
}
Environment.Exit(1);
}
public static string Args(params string[] args)
{
return string.Join(" ", args.Select(EncodeParameterArgument).ToArray());
}
/// <summary>
/// Encodes an argument for passing into a program
/// </summary>
/// <param name="original">The value that should be received by the program</param>
/// <returns>The value which needs to be passed to the program for the original value
/// to come through</returns>
public static string EncodeParameterArgument(string original)
{
if (string.IsNullOrEmpty(original))
return original;
string value = Regex.Replace(original, @"(\\*)" + "\"", @"$1\$0");
value = Regex.Replace(value, @"^(.*\s.*?)(\\*)$", "\"$1$2$2\"");
return value;
}
public static Architecture DetectArchitecture(string assembly)
{
using (var reader = new BinaryReader(File.OpenRead(assembly)))
{
var header = reader.ReadUInt16();
if(header == 0x5a4d)
{
reader.BaseStream.Seek(60, SeekOrigin.Begin); // this location contains the offset for the PE header
var peOffset = reader.ReadUInt32();
reader.BaseStream.Seek(peOffset + 4, SeekOrigin.Begin);
var machine = reader.ReadUInt16();
if (machine == 0x8664) // IMAGE_FILE_MACHINE_AMD64
return Architecture.x64;
else if (machine == 0x014c) // IMAGE_FILE_MACHINE_I386
return Architecture.x86;
else if (machine == 0x0200) // IMAGE_FILE_MACHINE_IA64
return Architecture.x64;
else
return Architecture.Unknown;
} else
{
// Not a supported binary
return Architecture.Unknown;
}
}
}
public abstract class Keyboard
{
[Flags]
private enum KeyStates
{
None = 0,
Down = 1,
Toggled = 2
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern short GetKeyState(int keyCode);
private static KeyStates GetKeyState(Keys key)
{
KeyStates state = KeyStates.None;
short retVal = GetKeyState((int)key);
//If the high-order bit is 1, the key is down
//otherwise, it is up.
if ((retVal & 0x8000) == 0x8000)
state |= KeyStates.Down;
//If the low-order bit is 1, the key is toggled.
if ((retVal & 1) == 1)
state |= KeyStates.Toggled;
return state;
}
public static bool IsKeyDown(Keys key)
{
return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
}
public static bool IsKeyToggled(Keys key)
{
return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
}
}
}
}

+ 36
- 0
IPA/Properties/AssemblyInfo.cs View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Illusion Plugin Architecture")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Illusion Plugin Architecture")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("14092533-98bb-40a4-9afc-27bb75672a70")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.1.1.0")]
[assembly: AssemblyFileVersion("3.1.1.0")]

+ 61
- 0
IPA/Shortcut.cs View File

@ -0,0 +1,61 @@
using System;
using System.Runtime.InteropServices;
namespace IPA
{
public class Shortcut
{
private static Type m_type = Type.GetTypeFromProgID("WScript.Shell");
private static object m_shell = Activator.CreateInstance(m_type);
[ComImport, TypeLibType((short)0x1040), Guid("F935DC23-1CF0-11D0-ADB9-00C04FD58A0B")]
private interface IWshShortcut
{
[DispId(0)]
string FullName { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0)] get; }
[DispId(0x3e8)]
string Arguments { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e8)] set; }
[DispId(0x3e9)]
string Description { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3e9)] set; }
[DispId(0x3ea)]
string Hotkey { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ea)] set; }
[DispId(0x3eb)]
string IconLocation { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3eb)] set; }
[DispId(0x3ec)]
string RelativePath { [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ec)] set; }
[DispId(0x3ed)]
string TargetPath { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ed)] set; }
[DispId(0x3ee)]
int WindowStyle { [DispId(0x3ee)] get; [param: In] [DispId(0x3ee)] set; }
[DispId(0x3ef)]
string WorkingDirectory { [return: MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] get; [param: In, MarshalAs(UnmanagedType.BStr)] [DispId(0x3ef)] set; }
[TypeLibFunc((short)0x40), DispId(0x7d0)]
void Load([In, MarshalAs(UnmanagedType.BStr)] string PathLink);
[DispId(0x7d1)]
void Save();
}
public static void Create(string fileName, string targetPath, string arguments, string workingDirectory, string description, string hotkey, string iconPath)
{
IWshShortcut shortcut = (IWshShortcut)m_type.InvokeMember("CreateShortcut", System.Reflection.BindingFlags.InvokeMethod, null, m_shell, new object[] { fileName });
shortcut.Description = description;
shortcut.Hotkey = hotkey;
shortcut.TargetPath = targetPath;
shortcut.WorkingDirectory = workingDirectory;
shortcut.Arguments = arguments;
if (!string.IsNullOrEmpty(iconPath))
shortcut.IconLocation = iconPath;
shortcut.Save();
}
}
}

BIN
IPA/favicon.ico View File

Before After

+ 1
- 0
IPA/obj/Debug/IPA.csproj.CoreCompileInputs.cache View File

@ -0,0 +1 @@
f7c20aca6b99cd3b62d50a05d9bdca1eb41dca2a

+ 4
- 0
IPA/packages.config View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net35-client" />
</packages>

+ 30
- 0
IllusionInjector/Bootstrapper.cs View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace IllusionInjector
{
class Bootstrapper : MonoBehaviour
{
public event Action Destroyed = delegate {};
void Awake()
{
if (Environment.CommandLine.Contains("--verbose") && !Screen.fullScreen)
{
Windows.GuiConsole.CreateConsole();
}
}
void Start()
{
Destroy(gameObject);
}
void OnDestroy()
{
Destroyed();
}
}
}

+ 109
- 0
IllusionInjector/CompositePlugin.cs View File

@ -0,0 +1,109 @@
using IllusionPlugin;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace IllusionInjector
{
public class CompositePlugin : IPlugin
{
IEnumerable<IPlugin> plugins;
private delegate void CompositeCall(IPlugin plugin);
public CompositePlugin(IEnumerable<IPlugin> plugins)
{
this.plugins = plugins;
}
public void OnApplicationStart()
{
Invoke(plugin => plugin.OnApplicationStart());
}
public void OnApplicationQuit()
{
Invoke(plugin => plugin.OnApplicationQuit());
}
public void OnLevelWasLoaded(int level)
{
foreach (var plugin in plugins)
{
try
{
plugin.OnLevelWasLoaded(level);
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", plugin.Name, ex);
}
}
}
private void Invoke(CompositeCall callback)
{
foreach (var plugin in plugins)
{
try
{
callback(plugin);
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", plugin.Name, ex);
}
}
}
public void OnLevelWasInitialized(int level)
{
foreach (var plugin in plugins)
{
try
{
plugin.OnLevelWasInitialized(level);
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", plugin.Name, ex);
}
}
}
public void OnUpdate()
{
Invoke(plugin => plugin.OnUpdate());
}
public void OnFixedUpdate()
{
Invoke(plugin => plugin.OnFixedUpdate());
}
public string Name
{
get { throw new NotImplementedException(); }
}
public string Version
{
get { throw new NotImplementedException(); }
}
public void OnLateUpdate()
{
Invoke(plugin =>
{
if (plugin is IEnhancedPlugin)
((IEnhancedPlugin)plugin).OnLateUpdate();
});
}
}
}

+ 71
- 0
IllusionInjector/ConsoleWindow.cs View File

@ -0,0 +1,71 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
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);
}
}

+ 66
- 0
IllusionInjector/IllusionInjector.csproj View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D1C61AF5-0D2D-4752-8203-1C6929025F7C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IllusionInjector</RootNamespace>
<AssemblyName>IllusionInjector</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine">
<HintPath>..\Libs\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Bootstrapper.cs" />
<Compile Include="CompositePlugin.cs" />
<Compile Include="ConsoleWindow.cs" />
<Compile Include="Injector.cs" />
<Compile Include="PluginManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PluginComponent.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IllusionPlugin\IllusionPlugin.csproj">
<Project>{e2848bfb-5432-42f4-8ae0-d2ec0cdf2f71}</Project>
<Name>IllusionPlugin</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 25
- 0
IllusionInjector/Injector.cs View File

@ -0,0 +1,25 @@
using System;
using System.IO;
using UnityEngine;
namespace IllusionInjector
{
public static class Injector
{
private static bool injected = false;
public static void Inject()
{
if (!injected)
{
injected = true;
var bootstrapper = new GameObject("Bootstrapper").AddComponent<Bootstrapper>();
bootstrapper.Destroyed += Bootstrapper_Destroyed;
}
}
private static void Bootstrapper_Destroyed()
{
PluginComponent.Create();
}
}
}

+ 74
- 0
IllusionInjector/PluginComponent.cs View File

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace IllusionInjector
{
public class PluginComponent : MonoBehaviour
{
private CompositePlugin plugins;
private bool freshlyLoaded = false;
private bool quitting = false;
public static PluginComponent Create()
{
return new GameObject("IPA_PluginManager").AddComponent<PluginComponent>();
}
void Awake()
{
DontDestroyOnLoad(gameObject);
plugins = new CompositePlugin(PluginManager.Plugins);
plugins.OnApplicationStart();
}
void Start()
{
OnLevelWasLoaded(Application.loadedLevel);
}
void Update()
{
if (freshlyLoaded)
{
freshlyLoaded = false;
plugins.OnLevelWasInitialized(Application.loadedLevel);
}
plugins.OnUpdate();
}
void LateUpdate()
{
plugins.OnLateUpdate();
}
void FixedUpdate()
{
plugins.OnFixedUpdate();
}
void OnDestroy()
{
if (!quitting)
{
Create();
}
}
void OnApplicationQuit()
{
plugins.OnApplicationQuit();
quitting = true;
}
void OnLevelWasLoaded(int level)
{
plugins.OnLevelWasLoaded(level);
freshlyLoaded = true;
}
}
}

+ 128
- 0
IllusionInjector/PluginManager.cs View File

@ -0,0 +1,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();
}
}
}
}
}

+ 36
- 0
IllusionInjector/Properties/AssemblyInfo.cs View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("IllusionInjector")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("IllusionInjector")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("400a540a-d21f-4609-966b-206059b6e73b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 1
- 0
IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache View File

@ -0,0 +1 @@
207669803f9c3f5ead7136a41944fdaa372fd294

+ 21
- 21
LICENSE View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2018 Michael Guedko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License
Copyright (c) 2016
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

+ 91
- 0
Launcher/Launcher.csproj View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D1390268-F68B-4A55-B50D-EAD25756C8EF}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Launcher</RootNamespace>
<AssemblyName>Launcher</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>syringe.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<Content Include="syringe.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

+ 100
- 0
Launcher/Program.cs View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace Launcher
{
static class Program
{
private static string[] TABOO_NAMES = {
//"Start",
//"Update",
//"Awake",
//"OnDestroy"
};
private static string[] ENTRY_TYPES = { "Display" };
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
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");
EnsureIPA(executable);
StartGame(executable, args.ToArray());
}
else
{
MessageBox.Show("Could not find: " + file.FullName, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch(Exception globalException) {
MessageBox.Show(globalException.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static void EnsureIPA(string executable)
{
var processStart = new ProcessStartInfo("IPA.exe", EncodeParameterArgument(executable) + " --nowait");
processStart.UseShellExecute = false;
processStart.CreateNoWindow = true;
processStart.RedirectStandardError = true;
var process = Process.Start(processStart);
process.WaitForExit();
if(process.ExitCode != 0)
{
Fail(process.StandardError.ReadToEnd());
}
}
private static void StartGame(string executable, string[] args)
{
var arguments = string.Join(" ", args.ToArray());
Process.Start(executable, arguments);
}
private static void Fail(string reason) {
throw new Exception(reason);
}
/// <summary>
/// Encodes an argument for passing into a program
/// </summary>
/// <param name="original">The value that should be received by the program</param>
/// <returns>The value which needs to be passed to the program for the original value
/// to come through</returns>
private static string EncodeParameterArgument(string original)
{
if (string.IsNullOrEmpty(original))
return original;
string value = Regex.Replace(original, @"(\\*)" + "\"", @"$1\$0");
value = Regex.Replace(value, @"^(.*\s.*?)(\\*)$", "\"$1$2$2\"");
return value;
}
}
}

+ 36
- 0
Launcher/Properties/AssemblyInfo.cs View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Launcher")]
[assembly: AssemblyDescription("Rename to [EXE]_Patched.exe or [EXE]VR.exe")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Launcher")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d590f676-c2c0-4b80-ae93-6edf274320e6")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63
- 0
Launcher/Properties/Resources.Designer.cs View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Launcher.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Launcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

+ 117
- 0
Launcher/Properties/Resources.resx View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

+ 26
- 0
Launcher/Properties/Settings.Designer.cs View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Launcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

+ 7
- 0
Launcher/Properties/Settings.settings View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

+ 63
- 0
Launcher/Resources.Designer.cs View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Launcher {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Launcher.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

+ 121
- 0
Launcher/Resources.resx View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</root>

+ 1
- 0
Launcher/obj/Debug/Launcher.csproj.CoreCompileInputs.cache View File

@ -0,0 +1 @@
7c6dbd91916854c83d27e1fd6e1b9ccedbe983b8

+ 4
- 0
Launcher/packages.config View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net35" />
</packages>

BIN
Launcher/syringe.ico View File

Before After

BIN
Libs/UnityEngine.dll View File


Loading…
Cancel
Save