Skip to content

Commit 0326873

Browse files
authored
Merge pull request #114 from kohanis/merge-upstream-2.3.3.0
Merging upstream up to v2.3.3.0
2 parents 7c44c07 + b36abc5 commit 0326873

File tree

15 files changed

+362
-134
lines changed

15 files changed

+362
-134
lines changed

Harmony/Harmony.csproj

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,25 @@
2323
<DefaultItemExcludes>$(DefaultItemExcludes);Documentation/**</DefaultItemExcludes>
2424
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
2525
<CheckEolTargetFramework>false</CheckEolTargetFramework>
26-
<Version>$(HarmonyXVersion)</Version>
27-
<AssemblyVersion>$(HarmonyXVersionFull)</AssemblyVersion>
28-
<FileVersion>$(HarmonyXVersionFull)</FileVersion>
29-
<PackageVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</PackageVersion>
30-
<InformationalVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</InformationalVersion>
26+
<Version>$(HarmonyXVersion)</Version>
27+
<AssemblyVersion>$(HarmonyXVersionFull)</AssemblyVersion>
28+
<FileVersion>$(HarmonyXVersionFull)</FileVersion>
29+
<PackageVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</PackageVersion>
30+
<InformationalVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</InformationalVersion>
3131
<NoWarn>$(NoWarn);SYSLIB0011;NU5131</NoWarn>
32-
<Configurations>Debug;Release</Configurations>
33-
<PublishRepositoryUrl>true</PublishRepositoryUrl>
34-
<EmbedUntrackedSources>true</EmbedUntrackedSources>
35-
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
36-
<ClearOutputDirectory>True</ClearOutputDirectory>
32+
<Configurations>Debug;Release</Configurations>
33+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
34+
<EmbedUntrackedSources>true</EmbedUntrackedSources>
35+
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
36+
<ClearOutputDirectory>True</ClearOutputDirectory>
3737
<RootNamespace>HarmonyLib</RootNamespace>
38-
</PropertyGroup>
38+
</PropertyGroup>
3939

4040
<ItemGroup>
4141
<None Include="..\README.md" Pack="false" PackagePath="" />
4242
<None Include="..\LICENSE" Pack="true" PackagePath="" />
4343
<None Include="..\logo_mini.png" Pack="true" Visible="false" PackagePath="" />
44-
</ItemGroup>
44+
</ItemGroup>
4545

4646
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
4747
<Optimize>false</Optimize>
@@ -55,22 +55,22 @@
5555
<DebugType>portable</DebugType>
5656
<DebugSymbols>true</DebugSymbols>
5757
</PropertyGroup>
58-
58+
5959
<ItemGroup>
6060
<PackageReference Include="MonoMod.RuntimeDetour" Version="$(MonoModRuntimeDetour)" />
6161
</ItemGroup>
6262

63-
<ItemGroup>
63+
<ItemGroup>
6464
<!-- Reference assemblies are needed for non-Windows .NET Framework targeting builds. -->
6565
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
66-
67-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
66+
67+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
6868
</ItemGroup>
69-
70-
<ItemGroup Condition="$(TargetFramework)=='netstandard2.0'">
69+
70+
<ItemGroup Condition="$(TargetFramework)=='netstandard2.0'">
7171
<!-- Adding System.Reflection.Emit.* because there are public types exposed from its's package -->
7272
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" IncludeAssets="compile" />
73-
73+
7474
<!-- Minimal suitable major version -->
7575
<PackageReference Include="System.Text.Json" Version="5.0.2" />
7676
</ItemGroup>
@@ -85,23 +85,23 @@
8585
<Delete Files="@(OldNugetPackages)" />
8686
</Target>
8787

88-
<Target Name="CleanZip" AfterTargets="Clean">
89-
<ItemGroup>
90-
<OldZipFiles Include="$(MSBuildThisFileDirectory)bin\Harmony.*.zip" Condition="'$(Configuration)'=='Release'"/>
91-
</ItemGroup>
92-
<Delete Files="@(OldZipFiles)" />
93-
</Target>
88+
<Target Name="CleanZip" AfterTargets="Clean">
89+
<ItemGroup>
90+
<OldZipFiles Include="$(MSBuildThisFileDirectory)bin\Harmony.*.zip" Condition="'$(Configuration)'=='Release'" />
91+
</ItemGroup>
92+
<Delete Files="@(OldZipFiles)" />
93+
</Target>
9494

95-
<Target Name="RemoveExtraDlls" AfterTargets="Pack">
96-
<ItemGroup>
97-
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\MonoMod.*.*" />
98-
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\Mono.*.*" />
99-
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\System.*.*" />
100-
</ItemGroup>
101-
<Delete Files="@(ExtraDlls)" />
102-
</Target>
95+
<Target Name="RemoveExtraDlls" AfterTargets="Pack">
96+
<ItemGroup>
97+
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\MonoMod.*.*" />
98+
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\Mono.*.*" />
99+
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\System.*.*" />
100+
</ItemGroup>
101+
<Delete Files="@(ExtraDlls)" />
102+
</Target>
103103

104-
<Target Name="Zip" AfterTargets="RemoveExtraDlls" DependsOnTargets="CleanZip">
105-
<ZipDirectory SourceDirectory="$(MSBuildThisFileDirectory)bin\$(Configuration)" DestinationFile="$(MSBuildThisFileDirectory)bin\Harmony.$(Version).zip" Overwrite="true" Condition="'$(Configuration)'=='Release'"/>
106-
</Target>
104+
<Target Name="Zip" AfterTargets="RemoveExtraDlls" DependsOnTargets="CleanZip">
105+
<ZipDirectory SourceDirectory="$(MSBuildThisFileDirectory)bin\$(Configuration)" DestinationFile="$(MSBuildThisFileDirectory)bin\Harmony.$(Version).zip" Overwrite="true" Condition="'$(Configuration)'=='Release'" />
106+
</Target>
107107
</Project>

Harmony/Internal/PatchModels.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ internal class AttributePatch
8686
internal HarmonyMethod info;
8787
internal HarmonyPatchType? type;
8888

89-
static readonly string harmonyAttributeName = typeof(HarmonyAttribute).FullName;
9089
internal static IEnumerable<AttributePatch> Create(MethodInfo patch, bool collectIncomplete = false)
9190
{
9291
if (patch is null)
@@ -108,7 +107,7 @@ internal static IEnumerable<AttributePatch> Create(MethodInfo patch, bool collec
108107
var f_info = AccessTools.Field(attr.GetType(), nameof(HarmonyAttribute.info));
109108
return f_info.GetValue(attr);
110109
})
111-
.Select(harmonyInfo => AccessTools.MakeDeepCopy<HarmonyMethod>(harmonyInfo))
110+
.Select(AccessTools.MakeDeepCopy<HarmonyMethod>)
112111
.ToList();
113112

114113
var completeMethods = new List<HarmonyMethod>();

Harmony/Internal/Util/StackTraceFixes.cs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
using System;
77
using System.Diagnostics;
88
using System.Reflection;
9-
using MonoMod.Core.Platforms;
109
using MonoMod.RuntimeDetour;
11-
using MonoMod.Utils;
1210
using System.Linq;
1311

1412
namespace HarmonyLib.Internal.RuntimeFixes
@@ -32,28 +30,19 @@ public static void Install()
3230
}
3331

3432
// Helper to save the detour info after patch is complete
35-
private static void OnILChainRefresh(ILHookInfo self)
36-
{
37-
PatchManager.AddReplacementOriginal(
38-
PlatformTriple.Current.GetIdentifiable(self.Method.Method),
39-
PlatformTriple.Current.GetIdentifiable(self.Method.GetEndOfChain())
40-
);
41-
}
33+
private static void OnILChainRefresh(ILHookInfo self) =>
34+
PatchManager.AddReplacementOriginal(self.Method.Method, self.Method.GetEndOfChain());
4235

4336
static Assembly GetExecutingAssemblyReplacement()
4437
{
4538
var frames = new StackTrace().GetFrames();
46-
if (frames?.Skip(1).FirstOrDefault() is { } frame && Harmony.GetOriginalMethodFromStackframe(frame) is { } original)
39+
if (frames?.Skip(1).FirstOrDefault() is { } frame && Harmony.GetMethodFromStackframe(frame) is { } original)
4740
return original.Module.Assembly;
4841
return Assembly.GetExecutingAssembly();
4942
}
5043

51-
private static MethodBase GetMethodReplacement(StackFrame self)
52-
{
53-
var method = self.GetMethod();
54-
var original = PatchManager.GetOriginal(PlatformTriple.Current.GetIdentifiable(method) as MethodInfo);
55-
return original ?? method;
56-
}
44+
private static MethodBase GetMethodReplacement(StackFrame self) =>
45+
Harmony.GetMethodFromStackframe(self) ?? self.GetMethod();
5746

5847
// ReSharper disable InconsistentNaming
5948
private static readonly MethodInfo GetExecutingAssembly_MethodInfo =

Harmony/Public/Harmony.cs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public void PatchAllUncategorized(Assembly assembly)
156156
patchClasses.DoIf((patchClass => string.IsNullOrEmpty(patchClass.Category)), (patchClass => patchClass.Patch()));
157157
}
158158

159-
/// <summary>Searches an assembly for Harmony annotations with a specific category and uses them to create patches</summary>
159+
/// <summary>Searches the current assembly for Harmony annotations with a specific category and uses them to create patches</summary>
160160
/// <param name="category">Name of patch category</param>
161161
///
162162
public void PatchCategory(string category)
@@ -328,14 +328,40 @@ public void Unpatch(MethodBase original, MethodInfo patch)
328328
_ = processor.Unpatch(patch);
329329
}
330330

331+
/// <summary>Searches the current assembly for types with a specific category annotation and uses them to unpatch existing patches. Fully unpatching is not supported. Be careful, unpatching is global</summary>
332+
/// <param name="category">Name of patch category</param>
333+
///
334+
public void UnpatchCategory(string category)
335+
{
336+
var method = new StackTrace().GetFrame(1).GetMethod();
337+
var assembly = method.ReflectedType.Assembly;
338+
UnpatchCategory(assembly, category);
339+
}
340+
341+
/// <summary>Searches an assembly for types with a specific category annotation and uses them to unpatch existing patches. Fully unpatching is not supported. Be careful, unpatching is global</summary>
342+
/// <param name="assembly">The assembly</param>
343+
/// <param name="category">Name of patch category</param>
344+
///
345+
public void UnpatchCategory(Assembly assembly, string category)
346+
{
347+
AccessTools.GetTypesFromAssembly(assembly)
348+
.Where(type =>
349+
{
350+
var harmonyAttributes = HarmonyMethodExtensions.GetFromType(type);
351+
var containerAttributes = HarmonyMethod.Merge(harmonyAttributes);
352+
return containerAttributes.category == category;
353+
})
354+
.Do(type => CreateClassProcessor(type).Unpatch());
355+
}
356+
331357
/// <summary>Test for patches from a specific Harmony ID</summary>
332358
/// <param name="harmonyID">The Harmony ID</param>
333359
/// <returns>True if patches for this ID exist</returns>
334360
///
335361
public static bool HasAnyPatches(string harmonyID)
336362
{
337363
return GetAllPatchedMethods()
338-
.Select(original => GetPatchInfo(original))
364+
.Select(GetPatchInfo)
339365
.Any(info => info.Owners.Contains(harmonyID));
340366
}
341367

@@ -360,13 +386,13 @@ public IEnumerable<MethodBase> GetPatchedMethods()
360386
public static IEnumerable<MethodBase> GetAllPatchedMethods() => PatchProcessor.GetAllPatchedMethods();
361387

362388
/// <summary>Gets the original method from a given replacement method</summary>
363-
/// <param name="replacement">A replacement method, for example from a stacktrace</param>
389+
/// <param name="replacement">A replacement method (patched original method)</param>
364390
/// <returns>The original method/constructor or <c>null</c> if not found</returns>
365391
///
366392
public static MethodBase GetOriginalMethod(MethodInfo replacement)
367393
{
368394
if (replacement == null) throw new ArgumentNullException(nameof(replacement));
369-
return PatchManager.GetOriginal(replacement);
395+
return PatchManager.GetRealMethod(replacement, useReplacement: false);
370396
}
371397

372398
/// <summary>Tries to get the method from a stackframe including dynamic replacement methods</summary>
@@ -376,25 +402,24 @@ public static MethodBase GetOriginalMethod(MethodInfo replacement)
376402
public static MethodBase GetMethodFromStackframe(StackFrame frame)
377403
{
378404
if (frame == null) throw new ArgumentNullException(nameof(frame));
379-
return PatchManager.FindReplacement(frame) ?? frame.GetMethod();
405+
return PatchManager.GetStackFrameMethod(frame, useReplacement: true);
380406
}
381407

382408
/// <summary>Gets the original method from the stackframe and uses original if method is a dynamic replacement</summary>
383409
/// <param name="frame">The <see cref="StackFrame"/></param>
384410
/// <returns>The original method from that stackframe</returns>
385411
public static MethodBase GetOriginalMethodFromStackframe(StackFrame frame)
386412
{
387-
var member = GetMethodFromStackframe(frame);
388-
if (member is MethodInfo methodInfo)
389-
member = GetOriginalMethod(methodInfo) ?? member;
390-
return member;
413+
if (frame == null) throw new ArgumentNullException(nameof(frame));
414+
return PatchManager.GetStackFrameMethod(frame, useReplacement: false);
391415
}
392416

393417
/// <summary>Gets Harmony version for all active Harmony instances</summary>
394418
/// <param name="currentVersion">[out] The current Harmony version</param>
395419
/// <returns>A dictionary containing assembly versions keyed by Harmony IDs</returns>
396420
///
397-
public static Dictionary<string, Version> VersionInfo(out Version currentVersion) => PatchProcessor.VersionInfo(out currentVersion);
421+
public static Dictionary<string, Version> VersionInfo(out Version currentVersion)
422+
=> PatchProcessor.VersionInfo(out currentVersion);
398423

399424
private static int _autoGuidCounter = 100;
400425

Harmony/Public/HarmonyMethod.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,23 @@ public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detai
288288
{
289289
var baseValue = masterTrv.Field(f).GetValue();
290290
var detailValue = detailTrv.Field(f).GetValue();
291-
// This if is needed because priority defaults to -1
292-
// This causes the value of a HarmonyPriority attribute to be overriden by the next attribute if it is not merged last
293-
// should be removed by making priority nullable and default to null at some point
294-
if (f != nameof(HarmonyMethod.priority) || (int)detailValue != -1)
291+
if (f != nameof(HarmonyMethod.priority))
295292
SetValue(resultTrv, f, detailValue ?? baseValue);
293+
else
294+
{
295+
// This if is needed because priority defaults to -1
296+
// This causes the value of a HarmonyPriority attribute to be overriden by the next attribute if it is not merged last
297+
// should be removed by making priority nullable and default to null at some point
298+
299+
var baseInt = (int)baseValue;
300+
var detailInt = (int)detailValue;
301+
var priority = Math.Max(baseInt, detailInt);
302+
if (baseInt == -1 && detailInt != -1)
303+
priority = detailInt;
304+
if (baseInt != -1 && detailInt == -1)
305+
priority = baseInt;
306+
SetValue(resultTrv, f, priority);
307+
}
296308
});
297309
return result;
298310
}
@@ -313,7 +325,7 @@ static HarmonyMethod GetHarmonyMethodInfo(object attribute)
313325
public static List<HarmonyMethod> GetFromType(Type type)
314326
{
315327
return type.GetCustomAttributes(true)
316-
.Select(attr => GetHarmonyMethodInfo(attr))
328+
.Select(GetHarmonyMethodInfo)
317329
.Where(info => info is not null)
318330
.ToList();
319331
}
@@ -331,7 +343,7 @@ public static List<HarmonyMethod> GetFromType(Type type)
331343
public static List<HarmonyMethod> GetFromMethod(MethodBase method)
332344
{
333345
return method.GetCustomAttributes(true)
334-
.Select(attr => GetHarmonyMethodInfo(attr))
346+
.Select(GetHarmonyMethodInfo)
335347
.Where(info => info is not null)
336348
.ToList();
337349
}

Harmony/Public/Patch.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ internal static PatchInfo Deserialize(byte[] bytes)
113113
internal static int PriorityComparer(object obj, int index, int priority)
114114
{
115115
var trv = Traverse.Create(obj);
116-
var theirPriority = trv.Field("priority").GetValue<int>();
117-
var theirIndex = trv.Field("index").GetValue<int>();
116+
var theirPriority = trv.Field(nameof(Patch.priority)).GetValue<int>();
117+
var theirIndex = trv.Field(nameof(Patch.index)).GetValue<int>();
118118

119119
if (priority != theirPriority)
120120
return -(priority.CompareTo(theirPriority));

0 commit comments

Comments
 (0)