Improve stability.

This commit is contained in:
Eusth 2017-01-08 17:49:11 +01:00
parent 687135d55f
commit 6e691c3071
4 changed files with 56 additions and 20 deletions

View file

@ -72,6 +72,9 @@
<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.

View file

@ -10,7 +10,7 @@ namespace IPA.Patcher
{
class PatchedModule
{
private const string ENTRY_TYPE = "Display";
private static readonly string[] ENTRY_TYPES = { "Input", "Display" };
private FileInfo _File;
private ModuleDefinition _Module;
@ -57,29 +57,43 @@ namespace IPA.Patcher
// 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);
var targetType = FindEntryType();
if (targetType == null) throw new Exception("Couldn't find entry class. Aborting.");
var targetMethod = targetType.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
if (targetMethod == null)
int patched = 0;
foreach(var type in FindEntryTypes())
{
throw new Exception("Couldn't find entry method. Aborting.");
if(PatchType(type, injector))
{
patched++;
}
}
if(patched > 0)
{
_Module.Write(_File.FullName);
} else
{
throw new Exception("Could not find any entry type!");
}
}
var injector = ModuleDefinition.ReadModule(injectorPath);
var methodReference = _Module.Import(injector.GetType("IllusionInjector.Injector").Methods.First(m => m.Name == "Inject"));
targetMethod.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Call, methodReference));
_Module.Write(_File.FullName);
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 TypeDefinition FindEntryType()
private IEnumerable<TypeDefinition> FindEntryTypes()
{
return _Module.GetTypes().FirstOrDefault(m => m.Name == ENTRY_TYPE);
return _Module.GetTypes().Where(m => ENTRY_TYPES.Contains(m.Name));
}
}
}

View file

@ -49,17 +49,25 @@ namespace IPA.Patcher
{
VirtualizeType(type);
}
_Module.Write(_File.FullName);
}
private void VirtualizeType(TypeDefinition type)
{
if (type.IsSealed) return;
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)
{
@ -97,7 +105,10 @@ namespace IPA.Patcher
{
get
{
return _Module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake")).All(m => m.IsVirtual);
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;
}
}
}

View file

@ -20,7 +20,7 @@ namespace IPA
string managedFolder = Path.Combine("IPA", "Managed");
string pluginsFolder = "Plugins";
string projectName = Path.GetFileNameWithoutExtension(args[0]);
string dataPath = Path.Combine(Path.Combine(Environment.CurrentDirectory, projectName + "_Data"), "Managed");
string dataPath = Path.Combine(Path.Combine(Path.GetDirectoryName(args[0]), projectName + "_Data"), "Managed");
string engineFile = Path.Combine(dataPath, "UnityEngine.dll");
string assemblyFile = Path.Combine(dataPath, "Assembly-Csharp.dll");
@ -35,11 +35,13 @@ namespace IPA
try
{
// Copying
Console.Write("Updating files... ");
CopyAll(new DirectoryInfo(managedFolder), new DirectoryInfo(dataPath));
Console.WriteLine("Successfully copied files!");
Console.WriteLine("Successfully updated files!");
if(!Directory.Exists(pluginsFolder))
if (!Directory.Exists(pluginsFolder))
{
Console.WriteLine("Creating plugins folder... ");
Directory.CreateDirectory(pluginsFolder);
}
@ -47,21 +49,27 @@ namespace IPA
var patchedModule = PatchedModule.Load(engineFile);
if(!patchedModule.IsPatched)
{
Console.Write("Patching UnityEngine.dll... ");
BackupManager.MakeBackup(engineFile);
patchedModule.Patch();
Console.WriteLine("Done!");
}
// Virtualizing
var virtualizedModule = VirtualizedModule.Load(assemblyFile);
if(!virtualizedModule.IsVirtualized)
{
Console.Write("Virtualizing Assembly-Csharp.dll... ");
BackupManager.MakeBackup(assemblyFile);
virtualizedModule.Virtualize();
Console.WriteLine("Done!");
}
} catch(Exception e)
{
Fail("Oops! This should not have happened.\n\n" + e);
}
Console.WriteLine("Finished!");
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)