using System;
using System.Linq;
using Mono.Cecil;
using Version = SemanticVersioning.Version;
namespace BepInEx.Preloader.Core.Patching;
///
/// This attribute denotes that a class is a patcher plugin, and specifies the required metadata.
///
[AttributeUsage(AttributeTargets.Class)]
public class PatcherPluginInfoAttribute : Attribute
{
/// The unique identifier of the plugin. Should not change between plugin versions.
/// The user friendly name of the plugin. Is able to be changed between versions.
/// The specific version of the plugin.
public PatcherPluginInfoAttribute(string GUID, string Name, string Version)
{
this.GUID = GUID;
this.Name = Name;
this.Version = TryParseLongVersion(Version);
}
///
/// The unique identifier of the plugin. Should not change between plugin versions.
///
public string GUID { get; protected set; }
///
/// The user friendly name of the plugin. Is able to be changed between versions.
///
public string Name { get; protected set; }
///
/// The specific version of the plugin.
///
public Version Version { get; protected set; }
private static Version TryParseLongVersion(string version)
{
if (Version.TryParse(version, out var v))
return v;
// no System.Version.TryParse() on .NET 3.5
try
{
var longVersion = new System.Version(version);
return new Version(longVersion.Major, longVersion.Minor,
longVersion.Build != -1 ? longVersion.Build : 0);
}
catch { }
return null;
}
internal static PatcherPluginInfoAttribute FromCecilType(TypeDefinition td)
{
var attr = MetadataHelper.GetCustomAttributes(td, false).FirstOrDefault();
if (attr == null)
return null;
return new PatcherPluginInfoAttribute((string) attr.ConstructorArguments[0].Value,
(string) attr.ConstructorArguments[1].Value,
(string) attr.ConstructorArguments[2].Value);
}
internal static PatcherPluginInfoAttribute FromType(Type type)
{
var attributes = type.GetCustomAttributes(typeof(PatcherPluginInfoAttribute), false);
if (attributes.Length == 0)
return null;
return (PatcherPluginInfoAttribute) attributes[0];
}
}
///
/// Defines an assembly that a patch method will target.
///
[AttributeUsage(AttributeTargets.Method)]
public class TargetAssemblyAttribute : Attribute
{
///
/// Marker used to indicate all possible assemblies to be targeted by a patch method.
///
public const string AllAssemblies = "_all";
///
/// The short filename of the assembly. Use to mark all possible
/// assemblies as targets.
///
public TargetAssemblyAttribute(string targetAssembly)
{
TargetAssembly = targetAssembly;
}
///
/// The short filename of the assembly to target.
///
public string TargetAssembly { get; }
}
///
/// Defines a type that a patch method will target.
///
[AttributeUsage(AttributeTargets.Method)]
public class TargetTypeAttribute : Attribute
{
/// The short filename of the assembly of which belongs to.
/// The full name of the type to target for patching.
public TargetTypeAttribute(string targetAssembly, string targetType)
{
TargetAssembly = targetAssembly;
TargetType = targetType;
}
///
/// The short filename of the assembly to target.
///
public string TargetAssembly { get; }
///
/// The full name of the type to target for patching.
///
public string TargetType { get; }
}