Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
fix up and relax Dynamic some
Browse files Browse the repository at this point in the history
add some paranoia to OneStepAheadPatch
  • Loading branch information
Tyler-IN committed May 12, 2020
1 parent f226e0e commit 7ec1256
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 19 deletions.
30 changes: 19 additions & 11 deletions src/CommunityPatch/Dynamic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ private static void AccessInternals(Assembly asm) {
}
}


public static FieldRef<T, TField> BuildRef<T, TField>(this FieldInfo fieldInfo, bool skipVerification = true) {
if (fieldInfo == null)
throw new ArgumentNullException(nameof(fieldInfo));
Expand Down Expand Up @@ -82,7 +81,6 @@ public static FieldRef<T, TField> BuildRef<T, TField>(this FieldInfo fieldInfo,
return (FieldRef<T, TField>) dmi!.CreateDelegate(typeof(FieldRef<T, TField>));
}


public static Func<T, TField> BuildGetter<T, TField>(this FieldInfo fieldInfo, bool skipVerification = true) {
if (fieldInfo == null)
throw new ArgumentNullException(nameof(fieldInfo));
Expand Down Expand Up @@ -137,38 +135,48 @@ public static Action<T, TField> BuildSetter<T, TField>(this FieldInfo fieldInfo,
return (Action<T, TField>) dmi!.CreateDelegate(typeof(Action<T, TField>));
}

public static TDelegate BuildInvoker<TDelegate>(this MethodBase m) where TDelegate : Delegate {
public static TDelegate BuildInvoker<TDelegate>(this MethodBase m, bool skipVerification = true) where TDelegate : Delegate {
var td = typeof(TDelegate);
Dynamic.AccessInternals(m);
AccessInternals(m);
var dtMi = td.GetMethod("Invoke", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
var dtPs = dtMi!.GetParameters();
var dt = Dynamic.CreateStaticClass();
var mn = $"{m.Name}Invoker";
var d = Emit<TDelegate>.BuildStaticMethod(dt, mn, MethodAttributes.Public);
var d = Emit<TDelegate>.BuildStaticMethod(dt, mn, MethodAttributes.Public,
allowUnverifiableCode: skipVerification, doVerify: !skipVerification);
var ps = m.GetParameters();
if (m.IsStatic) {
for (ushort i = 0; i < ps.Length; i++) {
var p = ps[i];
var dp = dtPs[i];
if (p.ParameterType != dp.ParameterType)
if (!p.ParameterType.IsAssignableFrom(dp.ParameterType))
throw new NotImplementedException($"Unhandled parameter difference: {p.ParameterType.FullName} vs. {dp.ParameterType.FullName}");

d.LoadArgument(i);
if (p.ParameterType.IsByRef && !dp.ParameterType.IsByRef)
d.LoadArgumentAddress(i);
else
d.LoadArgument(i);
}
}
else {
var thisParamType = m.GetThisParamType();
if (dtPs[0].ParameterType != thisParamType)
throw new NotImplementedException($"Unhandled this parameter difference: {dtPs[0].ParameterType.FullName} vs. {thisParamType}");
if (thisParamType.IsValueType)
if (dtPs[0].ParameterType != typeof(object) && dtPs[0].ParameterType != thisParamType)
throw new NotImplementedException($"Unhandled this parameter difference: {dtPs[0].ParameterType.FullName} vs. {thisParamType}");
else if (dtPs[0].ParameterType != typeof(IntPtr) && dtPs[0].ParameterType != thisParamType)
throw new NotImplementedException($"Unhandled this parameter difference: {dtPs[0].ParameterType.FullName} vs. {thisParamType}");

d.LoadArgument(0);
for (var i = 0; i < ps.Length; i++) {
var p = ps[i];
var dp = dtPs[i + 1];
if (p.ParameterType != dp.ParameterType)
if (!p.ParameterType.IsAssignableFrom(dp.ParameterType))
throw new NotImplementedException($"Unhandled parameter difference: {p.ParameterType.FullName} vs. {dp.ParameterType.FullName}");

d.LoadArgument((ushort) (i + 1));
if (p.ParameterType.IsByRef && !dp.ParameterType.IsByRef)
d.LoadArgumentAddress((ushort) (i + 1));
else
d.LoadArgument((ushort) (i + 1));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public class OneStepAheadPatch : PerkPatchBase<OneStepAheadPatch> {

public override bool Applied { get; protected set; }

private static readonly Type MapNavigationHandler = Type.GetType("SandBox.View.Map.MapNavigationHandler, SandBox.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
private static readonly Type MapNavigationHandlerType = Type.GetType("SandBox.View.Map.MapNavigationHandler, SandBox.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

private static readonly MethodInfo TargetMethodInfo = MapNavigationHandler?.GetMethod("get_PartyEnabled", Public | Instance | DeclaredOnly);
private static readonly MethodInfo TargetMethodInfo = MapNavigationHandlerType?.GetMethod("get_PartyEnabled", Public | Instance | DeclaredOnly);

private static readonly MethodInfo PatchMethodInfo = typeof(OneStepAheadPatch).GetMethod(nameof(Postfix), Public | NonPublic | Static | DeclaredOnly);

Expand All @@ -33,6 +33,9 @@ public override IEnumerable<MethodBase> GetMethodsChecked() {
}
};

private static readonly Func<object,bool> MapNavHandlerPartyActiveGetter = MapNavigationHandlerType?.GetMethod("get_PartyActive", Public | Instance | DeclaredOnly)
?.BuildInvoker<Func<object,bool>>();

public OneStepAheadPatch() : base("V6mvBGDV") {
}

Expand All @@ -56,19 +59,14 @@ public override void Apply(Game game) {

public static void Postfix(ref bool __result, ref object __instance) {
if (__result) return;
if (IsPartyActive(__instance)) return;
if (MapNavHandlerPartyActiveGetter(__instance)) return;
if (Hero.MainHero.HeroState == Hero.CharacterStates.Prisoner) return;
if (MobileParty.MainParty.MapEvent == null) return;

var perk = ActivePatch.Perk;
__result = Hero.MainHero.GetPerkValue(perk);
}

private static bool IsPartyActive(object handler) {
var property = MapNavigationHandler.GetProperty("PartyActive", Public | Instance | DeclaredOnly);
return property != null && (bool) property.GetValue(handler);
}

}

}

0 comments on commit 7ec1256

Please sign in to comment.