Skip to content

Commit

Permalink
Refactored for release. This is v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pardeike committed Jan 6, 2017
1 parent 0fed06b commit a932502
Show file tree
Hide file tree
Showing 13 changed files with 394 additions and 160 deletions.
55 changes: 49 additions & 6 deletions Harmony/AccessTools.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

Expand Down Expand Up @@ -27,11 +28,11 @@ public static PropertyInfo Property(Type type, string name)
return type.GetProperty(name, all);
}

public static MethodInfo Method(Type type, string name, Type[] arguments = null)
public static MethodInfo Method(Type type, string name, Type[] parameters = null)
{
if (type == null || name == null) return null;
if (arguments == null) return type.GetMethod(name, all);
var result = type.GetMethod(name, all, null, arguments, null);
if (parameters == null) return type.GetMethod(name, all);
var result = type.GetMethod(name, all, null, parameters, null);
return result;
}

Expand All @@ -41,10 +42,32 @@ public static Type Inner(Type type, string name)
return type.GetNestedType(name, all);
}

public static Type[] GetTypes(object[] arguments)
public static Type[] GetTypes(object[] parameters)
{
if (arguments == null) return new Type[0];
return arguments.Select(a => a == null ? typeof(object) : a.GetType()).ToArray();
if (parameters == null) return new Type[0];
return parameters.Select(p => p == null ? typeof(object) : p.GetType()).ToArray();
}

public static List<string> GetFieldNames(Type type)
{
return type.GetFields(all).Select(f => f.Name).ToList();
}

public static List<string> GetFieldNames(object instance)
{
if (instance == null) return new List<string>();
return GetFieldNames(instance.GetType());
}

public static List<string> GetPropertyNames(Type type)
{
return type.GetProperties(all).Select(f => f.Name).ToList();
}

public static List<string> GetPropertyNames(object instance)
{
if (instance == null) return new List<string>();
return GetPropertyNames(instance.GetType());
}

public static object GetDefaultValue(Type type)
Expand All @@ -55,6 +78,26 @@ public static object GetDefaultValue(Type type)
return Activator.CreateInstance(type);
return null;
}

public static bool isStruct(Type type)
{
return type.IsValueType && !isValue(type) && !isVoid(type);
}

public static bool isClass(Type type)
{
return !type.IsValueType;
}

public static bool isValue(Type type)
{
return type.IsPrimitive || type.IsEnum;
}

public static bool isVoid(Type type)
{
return type == typeof(void);
}
}

public static class TypeExtensions
Expand Down
65 changes: 44 additions & 21 deletions Harmony/Attributes.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,82 @@
using System;
using System.Collections.Generic;

namespace Harmony
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class HarmonyPatch : Attribute
public class HarmonyAttribute : Attribute
{
public Type type;
public string methodName;
public Type[] parameter;
public HarmonyMethod info = new HarmonyMethod();
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class HarmonyPatch : HarmonyAttribute
{
public HarmonyPatch()
{
}

public HarmonyPatch(Type type)
{
this.type = type;
info.originalType = type;
}

public HarmonyPatch(string methodName)
{
this.methodName = methodName;
info.methodName = methodName;
}

public HarmonyPatch(Type[] parameter)
{
this.parameter = parameter;
info.parameter = parameter;
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class HarmonyPriority : HarmonyAttribute
{
public HarmonyPriority(int prioritiy)
{
info.prioritiy = prioritiy;
}
}

public static HarmonyPatch Merge(List<HarmonyPatch> attributes)
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class HarmonyBefore : HarmonyAttribute
{
public HarmonyBefore(params string[] before)
{
var result = new HarmonyPatch();
attributes.ForEach(attr =>
{
if (attr.type != null) result.type = attr.type;
if (attr.methodName != null) result.methodName = attr.methodName;
if (attr.parameter != null) result.parameter = attr.parameter;
});
return result;
info.before = before;
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class HarmonyAfter : HarmonyAttribute
{
public HarmonyAfter(params string[] after)
{
info.after = after;
}
}

// If you don't want to use the special method names you can annotate
// using the following attributes:

[AttributeUsage(AttributeTargets.Method)]
public class HarmonyPrefix : Attribute
public class HarmonyPrepare : Attribute
{
}

[AttributeUsage(AttributeTargets.Method)]
public class HarmonyPostfix : Attribute
public class HarmonyTargetMethod : Attribute
{
}

[AttributeUsage(AttributeTargets.Method)]
public class HarmonyPrepare : Attribute
public class HarmonyPrefix : Attribute
{
}

[AttributeUsage(AttributeTargets.Method)]
public class HarmonyPostfix : Attribute
{
}
}
1 change: 1 addition & 0 deletions Harmony/Harmony.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<Compile Include="FastAccess.cs" />
<Compile Include="FileLogger.cs" />
<Compile Include="HarmonyInstance.cs" />
<Compile Include="HarmonyMethod.cs" />
<Compile Include="HarmonyRegistry.cs" />
<Compile Include="MethodInvoker.cs" />
<Compile Include="MonoReflectionExtension.cs" />
Expand Down
16 changes: 13 additions & 3 deletions Harmony/HarmonyInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Harmony
{
public delegate void PatchCallback(MethodInfo original, MethodInfo prefixPatch, MethodInfo postfixPatch);
public delegate void PatchCallback(MethodInfo original, HarmonyMethod prefixPatch, HarmonyMethod postfixPatch);

public class HarmonyInstance
{
Expand All @@ -28,7 +28,7 @@ private HarmonyInstance(string id, ContactInfo contact)
{
this.id = id;
this.contact = contact;
patcher = new Patcher(this, delegate (MethodInfo original, MethodInfo prefixPatch, MethodInfo postfixPatch)
patcher = new Patcher(this, delegate (MethodInfo original, HarmonyMethod prefixPatch, HarmonyMethod postfixPatch)
{
var register = registry.GetRegisterPatch();
register(id, original, prefixPatch, postfixPatch);
Expand Down Expand Up @@ -77,7 +77,7 @@ public void PatchAll(Module module)
patcher.PatchAll(module);
}

public void Patch(MethodInfo original, MethodInfo prefix, MethodInfo postfix)
public void Patch(MethodInfo original, HarmonyMethod prefix, HarmonyMethod postfix)
{
patcher.Patch(original, prefix, postfix);
}
Expand All @@ -100,5 +100,15 @@ public class ContactInfo
public string steamURL;

public string website;

public override string ToString()
{
var trv = Traverse.Create(this);
var parts = AccessTools.GetFieldNames(this)
.Select(f => trv.Field(f).GetValue().ToString())
.Where(s => s != null && s != "")
.ToArray();
return "[" + string.Join(",", parts) + "]";
}
}
}
126 changes: 126 additions & 0 deletions Harmony/HarmonyMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Harmony
{
public class HarmonyMethod
{
public MethodInfo method; // need to be called 'method'

public Type originalType;
public string methodName;
public Type[] parameter;
public int prioritiy = -1;
public string[] before;
public string[] after;

public HarmonyMethod()
{
}

void ImportMethod(MethodInfo method)
{
this.method = method;
if (method != null)
{
var infos = method.GetHarmonyMethods();
if (infos != null)
Merge(infos).CopyTo(this);
}
}

public HarmonyMethod(MethodInfo method)
{
ImportMethod(method);
}

public HarmonyMethod(Type type, string name, Type[] parameters = null)
{
ImportMethod(AccessTools.Method(type, name, parameters));
}

public static List<string> HarmonyFields()
{
return AccessTools
.GetFieldNames(typeof(HarmonyMethod))
.Where(s => s != "method")
.ToList();
}

public static HarmonyMethod Merge(List<HarmonyMethod> attributes)
{
var result = new HarmonyMethod();
if (attributes == null) return result;
var resultTrv = Traverse.Create(result);
attributes.ForEach(attribute =>
{
var trv = Traverse.Create(attribute);
HarmonyFields().ForEach(f =>
{
var val = trv.Field(f).GetValue();
if (val != null)
resultTrv.Field(f).SetValue(val);
});
});
return result;
}
}

public static class HarmonyMethodExtensions
{
public static void CopyTo(this HarmonyMethod from, HarmonyMethod to)
{
if (to == null) return;
var fromTrv = Traverse.Create(from);
var toTrv = Traverse.Create(to);
HarmonyMethod.HarmonyFields().ForEach(f =>
{
var val = fromTrv.Field(f).GetValue();
if (val != null) toTrv.Field(f).SetValue(val);
});
}

public static HarmonyMethod Clone(this HarmonyMethod original)
{
var result = new HarmonyMethod();
original.CopyTo(result);
return result;
}

public static HarmonyMethod Merge(this HarmonyMethod master, HarmonyMethod detail)
{
if (detail == null) return master;
var result = new HarmonyMethod();
var resultTrv = Traverse.Create(result);
var masterTrv = Traverse.Create(master);
var detailTrv = Traverse.Create(detail);
HarmonyMethod.HarmonyFields().ForEach(f =>
{
var baseValue = masterTrv.Field(f).GetValue();
var detailValue = detailTrv.Field(f).GetValue();
resultTrv.Field(f).SetValue(detailValue != null ? detailValue : baseValue);
});
return result;
}

public static List<HarmonyMethod> GetHarmonyMethods(this Type type)
{
return type.GetCustomAttributes(true)
.Where(attr => attr is HarmonyAttribute)
.Cast<HarmonyAttribute>()
.Select(attr => attr.info)
.ToList();
}

public static List<HarmonyMethod> GetHarmonyMethods(this MethodInfo method)
{
return method.GetCustomAttributes(true)
.Where(attr => attr is HarmonyAttribute)
.Cast<HarmonyAttribute>()
.Select(attr => attr.info)
.ToList();
}
}
}
Loading

0 comments on commit a932502

Please sign in to comment.