2021-10-12 20:03:21 +00:00
using OWML.Common ;
2021-06-18 20:54:32 +00:00
using QSB.Utility ;
using System ;
using System.Collections.Generic ;
2021-06-19 12:55:04 +00:00
using System.Linq ;
2021-06-18 20:54:32 +00:00
using System.Reflection ;
namespace QSB.Patches
2020-11-03 21:11:10 +00:00
{
2020-12-02 21:23:01 +00:00
public abstract class QSBPatch
{
public abstract QSBPatchTypes Type { get ; }
public abstract void DoPatches ( ) ;
2021-06-18 20:54:32 +00:00
public void DoUnpatches ( )
{
foreach ( var item in _patchedMethods )
{
2021-08-08 19:04:55 +00:00
//DebugLog.DebugWrite($"[Unpatch] {item.DeclaringType}.{item.Name}", MessageType.Info);
2021-06-19 12:55:04 +00:00
Unpatch ( item ) ;
2021-06-18 20:54:32 +00:00
}
2021-06-18 21:38:32 +00:00
2021-06-18 20:54:32 +00:00
_patchedMethods . Clear ( ) ;
}
private List < MethodInfo > _patchedMethods = new List < MethodInfo > ( ) ;
public void Empty ( string patchName )
{
2021-08-08 19:04:55 +00:00
//DebugLog.DebugWrite($"[Empty] {patchName}", MessageType.Success);
2021-06-18 20:54:32 +00:00
var method = GetMethodInfo ( patchName ) ;
QSBCore . Helper . HarmonyHelper . EmptyMethod ( method ) ;
2021-08-08 19:05:12 +00:00
_patchedMethods . Add ( method ) ;
2021-06-18 20:54:32 +00:00
}
2021-08-21 18:52:35 +00:00
public void Prefix ( string patchName , params Type [ ] args )
= > DoPrefixPostfix ( true , patchName , args ) ;
2021-06-18 20:54:32 +00:00
2021-08-21 18:52:35 +00:00
public void Postfix ( string patchName , params Type [ ] args )
= > DoPrefixPostfix ( false , patchName , args ) ;
2021-06-18 20:54:32 +00:00
2021-08-21 18:52:35 +00:00
private void DoPrefixPostfix ( bool isPrefix , string patchName , params Type [ ] args )
2021-06-18 20:54:32 +00:00
{
2021-08-21 18:52:35 +00:00
var method = GetMethodInfo ( patchName , args ) ;
2021-06-18 20:54:32 +00:00
if ( method ! = null )
{
if ( isPrefix )
{
QSBCore . Helper . HarmonyHelper . AddPrefix ( method , GetType ( ) , patchName ) ;
}
else
{
QSBCore . Helper . HarmonyHelper . AddPostfix ( method , GetType ( ) , patchName ) ;
}
2021-06-18 21:38:32 +00:00
2021-06-18 20:54:32 +00:00
_patchedMethods . Add ( method ) ;
}
2021-08-08 19:04:55 +00:00
//DebugLog.DebugWrite($"{(isPrefix ? "[Prefix]" : "[Postfix]")} {patchName}", method == null ? MessageType.Error : MessageType.Success);
2021-06-18 20:54:32 +00:00
}
2021-08-21 18:52:35 +00:00
private MethodInfo GetMethodInfo ( string patchName , params Type [ ] args )
2021-06-18 20:54:32 +00:00
{
var splitName = patchName . Split ( '_' ) ;
var typeName = splitName [ 0 ] ;
var methodName = splitName [ 1 ] ;
var type = GetFirstTypeByName ( typeName ) ;
if ( type = = null )
{
2021-06-19 12:55:04 +00:00
DebugLog . ToConsole ( $"Error - Couldn't find type for patch name {patchName}!" , MessageType . Error ) ;
2021-06-18 20:54:32 +00:00
return null ;
}
2021-08-21 18:52:35 +00:00
var allMethodsOfName = type . GetMethods ( BindingFlags . Instance | BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . FlattenHierarchy ) . Where ( x = > x . Name = = methodName ) ;
if ( allMethodsOfName . Count ( ) = = 0 )
2021-06-18 20:54:32 +00:00
{
2021-08-21 18:52:35 +00:00
DebugLog . ToConsole ( $"Error - Could not find method {methodName} in type {typeName}." , MessageType . Error ) ;
2021-06-18 20:54:32 +00:00
return null ;
}
2021-08-21 18:52:35 +00:00
if ( allMethodsOfName . Count ( ) = = 1 )
{
return allMethodsOfName . First ( ) ;
}
DebugLog . DebugWrite ( $"More than one method found with name {methodName} in type {typeName}" ) ;
foreach ( var method in allMethodsOfName )
{
DebugLog . DebugWrite ( $"checking {method.Name}" ) ;
var paramList = method . GetParameters ( ) . Select ( x = > x . ParameterType ) ;
if ( Enumerable . SequenceEqual ( args , paramList ) )
{
DebugLog . DebugWrite ( $"match!" ) ;
return method ;
}
}
DebugLog . DebugWrite ( $"nothing found" ) ;
DebugLog . ToConsole ( $"Error - Could not find method {methodName} in type {typeName} with parameter list of {string.Join(" , ", args.Select(x => x.FullName).ToArray())}" , MessageType . Error ) ;
foreach ( var method in allMethodsOfName )
{
var paramList = method . GetParameters ( ) . Select ( x = > x . ParameterType ) ;
DebugLog . ToConsole ( $"- Found {method.Name}, but with params {string.Join(" , ", paramList.Select(x => x.FullName).ToArray())}" , MessageType . Error ) ;
}
2021-08-22 16:17:46 +00:00
2021-08-21 18:52:35 +00:00
return null ;
2021-06-18 20:54:32 +00:00
}
private Type GetFirstTypeByName ( string typeName )
{
var a = typeof ( OWRigidbody ) . Assembly ;
var assemblyTypes = a . GetTypes ( ) ;
2021-06-19 12:55:04 +00:00
for ( var j = 0 ; j < assemblyTypes . Length ; j + + )
2021-06-18 20:54:32 +00:00
{
if ( assemblyTypes [ j ] . Name = = typeName )
{
return assemblyTypes [ j ] ;
}
}
2021-06-18 21:38:32 +00:00
2021-06-18 20:54:32 +00:00
return null ;
}
2021-06-19 12:55:04 +00:00
private void Unpatch ( MethodInfo method )
{
2021-10-12 15:56:07 +00:00
/ *
2021-06-19 12:55:04 +00:00
var dictionary = typeof ( HarmonySharedState ) . Invoke < Dictionary < MethodBase , byte [ ] > > ( "GetState" , new object [ 0 ] ) ;
var methodBase = dictionary . Keys . First ( m = >
2021-07-04 21:34:38 +00:00
m . DeclaringType = = method . DeclaringType
2021-06-19 12:55:04 +00:00
& & m . Name = = method . Name ) ;
var patchInfo = PatchInfoSerialization . Deserialize ( dictionary . GetValueSafe ( methodBase ) ) ;
patchInfo . RemovePostfix ( QSBCore . Helper . Manifest . UniqueName ) ;
patchInfo . RemovePrefix ( QSBCore . Helper . Manifest . UniqueName ) ;
patchInfo . RemoveTranspiler ( QSBCore . Helper . Manifest . UniqueName ) ;
PatchFunctions . UpdateWrapper ( methodBase , patchInfo , QSBCore . Helper . Manifest . UniqueName ) ;
dictionary [ methodBase ] = patchInfo . Serialize ( ) ;
2021-10-12 15:56:07 +00:00
* /
2021-06-19 12:55:04 +00:00
}
2020-12-02 21:23:01 +00:00
}
2020-12-03 08:28:05 +00:00
}