Skip to content

Commit

Permalink
v2.1 release
Browse files Browse the repository at this point in the history
  • Loading branch information
pardeike committed Jul 5, 2021
1 parent 45a4a64 commit b906d04
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>

<PropertyGroup>
<MonoModCommonVersion>21.1.12.5</MonoModCommonVersion>
<MonoModCommonVersion>21.6.21.1</MonoModCommonVersion>
</PropertyGroup>

</Project>
6 changes: 3 additions & 3 deletions Harmony/Harmony.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
<Authors>Andreas Pardeike</Authors>
<AssemblyName>0Harmony</AssemblyName>
<SignAssembly>true</SignAssembly>
<Version>2.0.5.0</Version>
<Version>2.1.0.0</Version>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageProjectUrl>https://github.com/pardeike/Harmony</PackageProjectUrl>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageTags>Harmony,Mono,Patch,Patching,Runtime,Detour,Detours,Aspect,Aspects</PackageTags>
<AssemblyVersion>2.0.5.0</AssemblyVersion>
<FileVersion>2.0.5.0</FileVersion>
<AssemblyVersion>2.1.0.0</AssemblyVersion>
<FileVersion>2.1.0.0</FileVersion>
<PackageIcon>HarmonyLogo.png</PackageIcon>
<PackageIconUrl>https://raw.githubusercontent.com/pardeike/Harmony/master/HarmonyLogo.png</PackageIconUrl>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand Down
28 changes: 19 additions & 9 deletions Harmony/Internal/MethodPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal class MethodPatcher
const string RESULT_VAR = "__result";
const string STATE_VAR = "__state";
const string EXCEPTION_VAR = "__exception";
const string RUN_ORIGINA_VAR = "__runOriginal";
const string PARAM_INDEX_PREFIX = "__";
const string INSTANCE_FIELD_PREFIX = "___";

Expand Down Expand Up @@ -92,14 +93,14 @@ internal MethodInfo CreateReplacement(out Dictionary<int, CodeInstruction> final

prefixes.Union(postfixes).Union(finalizers).ToList().ForEach(fix =>
{
if (fix.DeclaringType is object && privateVars.ContainsKey(fix.DeclaringType.FullName) is false)
if (fix.DeclaringType is object && privateVars.ContainsKey(fix.DeclaringType.AssemblyQualifiedName) is false)
{
fix.GetParameters()
.Where(patchParam => patchParam.Name == STATE_VAR)
.Do(patchParam =>
{
var privateStateVariable = DeclareLocalVariable(patchParam.ParameterType);
privateVars[fix.DeclaringType.FullName] = privateStateVariable;
privateVars[fix.DeclaringType.AssemblyQualifiedName] = privateStateVariable;
});
}
});
Expand Down Expand Up @@ -358,7 +359,7 @@ bool EmitOriginalBaseMethod()
return true;
}

void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variables, bool allowFirsParamPassthrough, out LocalBuilder tmpObjectVar, List<KeyValuePair<LocalBuilder, Type>> tmpBoxVars)
void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variables, LocalBuilder runOriginalVariable, bool allowFirsParamPassthrough, out LocalBuilder tmpObjectVar, List<KeyValuePair<LocalBuilder, Type>> tmpBoxVars)
{
tmpObjectVar = null;
var isInstance = original.IsStatic is false;
Expand All @@ -381,6 +382,15 @@ void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variab
continue;
}

if (patchParam.Name == RUN_ORIGINA_VAR)
{
if (runOriginalVariable != null)
emitter.Emit(OpCodes.Ldloc, runOriginalVariable);
else
emitter.Emit(OpCodes.Ldc_I4_0);
continue;
}

if (patchParam.Name == INSTANCE_PARAM)
{
if (original.IsStatic)
Expand Down Expand Up @@ -415,13 +425,13 @@ void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variab
// field access by index only works for declared fields
fieldInfo = AccessTools.DeclaredField(original.DeclaringType, int.Parse(fieldName));
if (fieldInfo is null)
throw new ArgumentException($"No field found at given index in class {original.DeclaringType.FullName}", fieldName);
throw new ArgumentException($"No field found at given index in class {original.DeclaringType.AssemblyQualifiedName}", fieldName);
}
else
{
fieldInfo = AccessTools.Field(original.DeclaringType, fieldName);
if (fieldInfo is null)
throw new ArgumentException($"No such field defined in class {original.DeclaringType.FullName}", fieldName);
throw new ArgumentException($"No such field defined in class {original.DeclaringType.AssemblyQualifiedName}", fieldName);
}

if (fieldInfo.IsStatic)
Expand All @@ -438,7 +448,7 @@ void EmitCallParameter(MethodInfo patch, Dictionary<string, LocalBuilder> variab
if (patchParam.Name == STATE_VAR)
{
var ldlocCode = patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc;
if (variables.TryGetValue(patch.DeclaringType.FullName, out var stateVar))
if (variables.TryGetValue(patch.DeclaringType.AssemblyQualifiedName, out var stateVar))
emitter.Emit(ldlocCode, stateVar);
else
emitter.Emit(OpCodes.Ldnull);
Expand Down Expand Up @@ -642,7 +652,7 @@ void AddPrefixes(Dictionary<string, LocalBuilder> variables, LocalBuilder runOri
}
var tmpBoxVars = new List<KeyValuePair<LocalBuilder, Type>>();
EmitCallParameter(fix, variables, false, out var tmpObjectVar, tmpBoxVars);
EmitCallParameter(fix, variables, runOriginalVariable, false, out var tmpObjectVar, tmpBoxVars);
emitter.Emit(OpCodes.Call, fix);
if (tmpObjectVar != null)
{
Expand Down Expand Up @@ -685,7 +695,7 @@ bool AddPostfixes(Dictionary<string, LocalBuilder> variables, bool passthroughPa
throw new Exception("Methods without body cannot have postfixes. Use a transpiler instead.");
var tmpBoxVars = new List<KeyValuePair<LocalBuilder, Type>>();
EmitCallParameter(fix, variables, true, out var tmpObjectVar, tmpBoxVars);
EmitCallParameter(fix, variables, null, true, out var tmpObjectVar, tmpBoxVars);
emitter.Emit(OpCodes.Call, fix);
if (tmpObjectVar != null)
{
Expand Down Expand Up @@ -732,7 +742,7 @@ bool AddFinalizers(Dictionary<string, LocalBuilder> variables, bool catchExcepti
emitter.MarkBlockBefore(new ExceptionBlock(ExceptionBlockType.BeginExceptionBlock), out var label);
var tmpBoxVars = new List<KeyValuePair<LocalBuilder, Type>>();
EmitCallParameter(fix, variables, false, out var tmpObjectVar, tmpBoxVars);
EmitCallParameter(fix, variables, null, false, out var tmpObjectVar, tmpBoxVars);
emitter.Emit(OpCodes.Call, fix);
if (tmpObjectVar != null)
{
Expand Down
6 changes: 5 additions & 1 deletion Harmony/Public/Harmony.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using MonoMod.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand Down Expand Up @@ -50,7 +51,9 @@ public Harmony(string id)
#if !NET5_0
if (string.IsNullOrEmpty(location)) location = new Uri(assembly.CodeBase).LocalPath;
#endif
FileLog.Log($"### Harmony id={id}, version={version}, location={location}, env/clr={environment}, platform={platform}");
var ptr_runtime = IntPtr.Size;
var ptr_env = PlatformHelper.Current;
FileLog.Log($"### Harmony id={id}, version={version}, location={location}, env/clr={environment}, platform={platform}, ptrsize:runtime/env={ptr_runtime}/{ptr_env}");
var callingMethod = AccessTools.GetOutsideCaller();
if (callingMethod.DeclaringType is object)
{
Expand All @@ -68,6 +71,7 @@ public Harmony(string id)
}

/// <summary>Searches the current assembly for Harmony annotations and uses them to create patches</summary>
/// <remarks>This method can fail to use the correct assembly when being inlined. It calls StackTrace.GetFrame(1) which can point to the wrong method/assembly. If you are unsure or run into problems, use <code>PatchAll(Assembly.GetExecutingAssembly())</code> instead.</remarks>
///
public void PatchAll()
{
Expand Down
29 changes: 29 additions & 0 deletions HarmonyTests/Patching/Assets/PatchClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,35 @@ public static void Postfix(ref object __result)
}
}

public class Class22
{
public static bool? bool1 = null;
public static bool? bool2 = null;

[MethodImpl(MethodImplOptions.NoInlining)]
public static void Method22()
{
try
{
}
catch
{
throw;
}
}

public static bool Prefix1(bool __runOriginal)
{
bool1 = __runOriginal;
return false;
}

public static void Prefix2(bool __runOriginal)
{
bool2 = __runOriginal;
}
}

public class InjectDelegateBaseClass
{
public string pre;
Expand Down
29 changes: 29 additions & 0 deletions HarmonyTests/Patching/StaticPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -402,5 +402,34 @@ public void Test_Class18()
Assert.IsTrue(Class18Patch.prefixExecuted, "prefixExecuted");
Assert.AreEqual((float)1, color.r);
}

[Test]
public void Test_Class22()
{
var instance = new Harmony("test");
Assert.NotNull(instance, "instance");

var original = SymbolExtensions.GetMethodInfo(() => Class22.Method22());
Assert.NotNull(original, "original");
var prefix1 = SymbolExtensions.GetMethodInfo(() => Class22.Prefix1(false));
Assert.NotNull(original, "prefix1");
var prefix2 = SymbolExtensions.GetMethodInfo(() => Class22.Prefix2(false));
Assert.NotNull(original, "prefix2");

var patched1 = instance.Patch(original, new HarmonyMethod(prefix1));
Assert.NotNull(patched1, "patched1");

var patched2 = instance.Patch(original, new HarmonyMethod(prefix2));
Assert.NotNull(patched2, "patched2");

Class22.bool1 = null;
Class22.bool2 = null;
Class22.Method22();

Assert.NotNull(Class22.bool1, "Class22.bool1");
Assert.NotNull(Class22.bool2, "Class22.bool2");
Assert.IsTrue(Class22.bool1.Value, "Class22.bool1.Value");
Assert.IsFalse(Class22.bool2.Value, "Class22.bool2.Value");
}
}
}

0 comments on commit b906d04

Please sign in to comment.