Skip to content

Commit

Permalink
Merge pull request #114 from kohanis/merge-upstream-2.3.3.0
Browse files Browse the repository at this point in the history
Merging upstream up to v2.3.3.0
  • Loading branch information
ManlyMarco authored Jun 1, 2024
2 parents 7c44c07 + b36abc5 commit 0326873
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 134 deletions.
72 changes: 36 additions & 36 deletions Harmony/Harmony.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@
<DefaultItemExcludes>$(DefaultItemExcludes);Documentation/**</DefaultItemExcludes>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<Version>$(HarmonyXVersion)</Version>
<AssemblyVersion>$(HarmonyXVersionFull)</AssemblyVersion>
<FileVersion>$(HarmonyXVersionFull)</FileVersion>
<PackageVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</PackageVersion>
<InformationalVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</InformationalVersion>
<Version>$(HarmonyXVersion)</Version>
<AssemblyVersion>$(HarmonyXVersionFull)</AssemblyVersion>
<FileVersion>$(HarmonyXVersionFull)</FileVersion>
<PackageVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</PackageVersion>
<InformationalVersion>$(HarmonyXVersion)$(HarmonyXVersionSuffix)</InformationalVersion>
<NoWarn>$(NoWarn);SYSLIB0011;NU5131</NoWarn>
<Configurations>Debug;Release</Configurations>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<ClearOutputDirectory>True</ClearOutputDirectory>
<Configurations>Debug;Release</Configurations>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<ClearOutputDirectory>True</ClearOutputDirectory>
<RootNamespace>HarmonyLib</RootNamespace>
</PropertyGroup>
</PropertyGroup>

<ItemGroup>
<None Include="..\README.md" Pack="false" PackagePath="" />
<None Include="..\LICENSE" Pack="true" PackagePath="" />
<None Include="..\logo_mini.png" Pack="true" Visible="false" PackagePath="" />
</ItemGroup>
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<Optimize>false</Optimize>
Expand All @@ -55,22 +55,22 @@
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MonoMod.RuntimeDetour" Version="$(MonoModRuntimeDetour)" />
</ItemGroup>

<ItemGroup>
<ItemGroup>
<!-- Reference assemblies are needed for non-Windows .NET Framework targeting builds. -->
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>

<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework)=='netstandard2.0'">

<ItemGroup Condition="$(TargetFramework)=='netstandard2.0'">
<!-- Adding System.Reflection.Emit.* because there are public types exposed from its's package -->
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" IncludeAssets="compile" />

<!-- Minimal suitable major version -->
<PackageReference Include="System.Text.Json" Version="5.0.2" />
</ItemGroup>
Expand All @@ -85,23 +85,23 @@
<Delete Files="@(OldNugetPackages)" />
</Target>

<Target Name="CleanZip" AfterTargets="Clean">
<ItemGroup>
<OldZipFiles Include="$(MSBuildThisFileDirectory)bin\Harmony.*.zip" Condition="'$(Configuration)'=='Release'"/>
</ItemGroup>
<Delete Files="@(OldZipFiles)" />
</Target>
<Target Name="CleanZip" AfterTargets="Clean">
<ItemGroup>
<OldZipFiles Include="$(MSBuildThisFileDirectory)bin\Harmony.*.zip" Condition="'$(Configuration)'=='Release'" />
</ItemGroup>
<Delete Files="@(OldZipFiles)" />
</Target>

<Target Name="RemoveExtraDlls" AfterTargets="Pack">
<ItemGroup>
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\MonoMod.*.*" />
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\Mono.*.*" />
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\System.*.*" />
</ItemGroup>
<Delete Files="@(ExtraDlls)" />
</Target>
<Target Name="RemoveExtraDlls" AfterTargets="Pack">
<ItemGroup>
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\MonoMod.*.*" />
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\Mono.*.*" />
<ExtraDlls Include="$(MSBuildThisFileDirectory)bin\**\System.*.*" />
</ItemGroup>
<Delete Files="@(ExtraDlls)" />
</Target>

<Target Name="Zip" AfterTargets="RemoveExtraDlls" DependsOnTargets="CleanZip">
<ZipDirectory SourceDirectory="$(MSBuildThisFileDirectory)bin\$(Configuration)" DestinationFile="$(MSBuildThisFileDirectory)bin\Harmony.$(Version).zip" Overwrite="true" Condition="'$(Configuration)'=='Release'"/>
</Target>
<Target Name="Zip" AfterTargets="RemoveExtraDlls" DependsOnTargets="CleanZip">
<ZipDirectory SourceDirectory="$(MSBuildThisFileDirectory)bin\$(Configuration)" DestinationFile="$(MSBuildThisFileDirectory)bin\Harmony.$(Version).zip" Overwrite="true" Condition="'$(Configuration)'=='Release'" />
</Target>
</Project>
3 changes: 1 addition & 2 deletions Harmony/Internal/PatchModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ internal class AttributePatch
internal HarmonyMethod info;
internal HarmonyPatchType? type;

static readonly string harmonyAttributeName = typeof(HarmonyAttribute).FullName;
internal static IEnumerable<AttributePatch> Create(MethodInfo patch, bool collectIncomplete = false)
{
if (patch is null)
Expand All @@ -108,7 +107,7 @@ internal static IEnumerable<AttributePatch> Create(MethodInfo patch, bool collec
var f_info = AccessTools.Field(attr.GetType(), nameof(HarmonyAttribute.info));
return f_info.GetValue(attr);
})
.Select(harmonyInfo => AccessTools.MakeDeepCopy<HarmonyMethod>(harmonyInfo))
.Select(AccessTools.MakeDeepCopy<HarmonyMethod>)
.ToList();

var completeMethods = new List<HarmonyMethod>();
Expand Down
21 changes: 5 additions & 16 deletions Harmony/Internal/Util/StackTraceFixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
using System;
using System.Diagnostics;
using System.Reflection;
using MonoMod.Core.Platforms;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using System.Linq;

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

// Helper to save the detour info after patch is complete
private static void OnILChainRefresh(ILHookInfo self)
{
PatchManager.AddReplacementOriginal(
PlatformTriple.Current.GetIdentifiable(self.Method.Method),
PlatformTriple.Current.GetIdentifiable(self.Method.GetEndOfChain())
);
}
private static void OnILChainRefresh(ILHookInfo self) =>
PatchManager.AddReplacementOriginal(self.Method.Method, self.Method.GetEndOfChain());

static Assembly GetExecutingAssemblyReplacement()
{
var frames = new StackTrace().GetFrames();
if (frames?.Skip(1).FirstOrDefault() is { } frame && Harmony.GetOriginalMethodFromStackframe(frame) is { } original)
if (frames?.Skip(1).FirstOrDefault() is { } frame && Harmony.GetMethodFromStackframe(frame) is { } original)
return original.Module.Assembly;
return Assembly.GetExecutingAssembly();
}

private static MethodBase GetMethodReplacement(StackFrame self)
{
var method = self.GetMethod();
var original = PatchManager.GetOriginal(PlatformTriple.Current.GetIdentifiable(method) as MethodInfo);
return original ?? method;
}
private static MethodBase GetMethodReplacement(StackFrame self) =>
Harmony.GetMethodFromStackframe(self) ?? self.GetMethod();

// ReSharper disable InconsistentNaming
private static readonly MethodInfo GetExecutingAssembly_MethodInfo =
Expand Down
45 changes: 35 additions & 10 deletions Harmony/Public/Harmony.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public void PatchAllUncategorized(Assembly assembly)
patchClasses.DoIf((patchClass => string.IsNullOrEmpty(patchClass.Category)), (patchClass => patchClass.Patch()));
}

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

/// <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>
/// <param name="category">Name of patch category</param>
///
public void UnpatchCategory(string category)
{
var method = new StackTrace().GetFrame(1).GetMethod();
var assembly = method.ReflectedType.Assembly;
UnpatchCategory(assembly, category);
}

/// <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>
/// <param name="assembly">The assembly</param>
/// <param name="category">Name of patch category</param>
///
public void UnpatchCategory(Assembly assembly, string category)
{
AccessTools.GetTypesFromAssembly(assembly)
.Where(type =>
{
var harmonyAttributes = HarmonyMethodExtensions.GetFromType(type);
var containerAttributes = HarmonyMethod.Merge(harmonyAttributes);
return containerAttributes.category == category;
})
.Do(type => CreateClassProcessor(type).Unpatch());
}

/// <summary>Test for patches from a specific Harmony ID</summary>
/// <param name="harmonyID">The Harmony ID</param>
/// <returns>True if patches for this ID exist</returns>
///
public static bool HasAnyPatches(string harmonyID)
{
return GetAllPatchedMethods()
.Select(original => GetPatchInfo(original))
.Select(GetPatchInfo)
.Any(info => info.Owners.Contains(harmonyID));
}

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

/// <summary>Gets the original method from a given replacement method</summary>
/// <param name="replacement">A replacement method, for example from a stacktrace</param>
/// <param name="replacement">A replacement method (patched original method)</param>
/// <returns>The original method/constructor or <c>null</c> if not found</returns>
///
public static MethodBase GetOriginalMethod(MethodInfo replacement)
{
if (replacement == null) throw new ArgumentNullException(nameof(replacement));
return PatchManager.GetOriginal(replacement);
return PatchManager.GetRealMethod(replacement, useReplacement: false);
}

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

/// <summary>Gets the original method from the stackframe and uses original if method is a dynamic replacement</summary>
/// <param name="frame">The <see cref="StackFrame"/></param>
/// <returns>The original method from that stackframe</returns>
public static MethodBase GetOriginalMethodFromStackframe(StackFrame frame)
{
var member = GetMethodFromStackframe(frame);
if (member is MethodInfo methodInfo)
member = GetOriginalMethod(methodInfo) ?? member;
return member;
if (frame == null) throw new ArgumentNullException(nameof(frame));
return PatchManager.GetStackFrameMethod(frame, useReplacement: false);
}

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

private static int _autoGuidCounter = 100;

Expand Down
24 changes: 18 additions & 6 deletions Harmony/Public/HarmonyMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,23 @@ public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detai
{
var baseValue = masterTrv.Field(f).GetValue();
var detailValue = detailTrv.Field(f).GetValue();
// This if is needed because priority defaults to -1
// This causes the value of a HarmonyPriority attribute to be overriden by the next attribute if it is not merged last
// should be removed by making priority nullable and default to null at some point
if (f != nameof(HarmonyMethod.priority) || (int)detailValue != -1)
if (f != nameof(HarmonyMethod.priority))
SetValue(resultTrv, f, detailValue ?? baseValue);
else
{
// This if is needed because priority defaults to -1
// This causes the value of a HarmonyPriority attribute to be overriden by the next attribute if it is not merged last
// should be removed by making priority nullable and default to null at some point
var baseInt = (int)baseValue;
var detailInt = (int)detailValue;
var priority = Math.Max(baseInt, detailInt);
if (baseInt == -1 && detailInt != -1)
priority = detailInt;
if (baseInt != -1 && detailInt == -1)
priority = baseInt;
SetValue(resultTrv, f, priority);
}
});
return result;
}
Expand All @@ -313,7 +325,7 @@ static HarmonyMethod GetHarmonyMethodInfo(object attribute)
public static List<HarmonyMethod> GetFromType(Type type)
{
return type.GetCustomAttributes(true)
.Select(attr => GetHarmonyMethodInfo(attr))
.Select(GetHarmonyMethodInfo)
.Where(info => info is not null)
.ToList();
}
Expand All @@ -331,7 +343,7 @@ public static List<HarmonyMethod> GetFromType(Type type)
public static List<HarmonyMethod> GetFromMethod(MethodBase method)
{
return method.GetCustomAttributes(true)
.Select(attr => GetHarmonyMethodInfo(attr))
.Select(GetHarmonyMethodInfo)
.Where(info => info is not null)
.ToList();
}
Expand Down
4 changes: 2 additions & 2 deletions Harmony/Public/Patch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ internal static PatchInfo Deserialize(byte[] bytes)
internal static int PriorityComparer(object obj, int index, int priority)
{
var trv = Traverse.Create(obj);
var theirPriority = trv.Field("priority").GetValue<int>();
var theirIndex = trv.Field("index").GetValue<int>();
var theirPriority = trv.Field(nameof(Patch.priority)).GetValue<int>();
var theirIndex = trv.Field(nameof(Patch.index)).GetValue<int>();

if (priority != theirPriority)
return -(priority.CompareTo(theirPriority));
Expand Down
Loading

0 comments on commit 0326873

Please sign in to comment.