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

Commit

Permalink
made TramplerPatch2 not panic e1.2.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler-IN committed May 12, 2020
1 parent 3b61b8a commit 3984daa
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 72 deletions.
27 changes: 14 additions & 13 deletions src/CommunityPatch/CommunityPatch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Configurations>Debug;Release</Configurations>
<Platform>x64</Platform>
<PlatformTarget>x64</PlatformTarget>
<RootNamespace />
<RootNamespace/>
<Title>Community Patch</Title>
<Authors>Tyler Young</Authors>
<Company>The Mount &amp; Blade II: Bannerlord Community</Company>
Expand All @@ -33,31 +33,32 @@
<Private>True</Private>
</Reference>
</ItemGroup>

<ItemGroup>
<None Include="..\..\SubModule.xml">
<Link>SubModule.xml</Link>
</None>
<None Include="..\..\README.md">
<Link>README.md</Link>
</None>
<None Remove="*.DotSettings" />
<None Remove="*.DotSettings"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="HardwareProviders.CPU.Standard" Version="2.0.1" />
<PackageReference Include="HardwareProviders.Standard" Version="2.0.1" />
<PackageReference Include="HardwareProviders.CPU.Standard" Version="2.0.1"/>
<PackageReference Include="HardwareProviders.Standard" Version="2.0.1"/>
<PackageReference Include="Lib.Harmony" Version="2.0.0.9" PrivateAssets="All">
<GeneratePathProperty>True</GeneratePathProperty>
<NoWarn>NU1701</NoWarn>
</PackageReference>
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.3" />
<PackageReference Include="Microsoft.SourceLink.Common" Version="1.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" />
<PackageReference Include="Sigil" Version="5.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
<PackageReference Include="TextCopy" Version="3.0.2" />
<PackageReference Include="Tomlyn" Version="0.1.2" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.3"/>
<PackageReference Include="Microsoft.SourceLink.Common" Version="1.0.0"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0"/>
<PackageReference Include="Sigil" Version="5.0.0"/>
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0"/>
<PackageReference Include="System.Reflection.Emit" Version="4.7.0"/>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1"/>
<PackageReference Include="TextCopy" Version="3.0.2"/>
<PackageReference Include="Tomlyn" Version="0.1.2"/>
</ItemGroup>

<ItemGroup>
Expand Down
63 changes: 30 additions & 33 deletions src/CommunityPatch/Patches/Perks/Endurance/Riding/TramplerPatch2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using TaleWorlds.CampaignSystem;
using TaleWorlds.Core;
using HarmonyLib;
using JetBrains.Annotations;
using TaleWorlds.Engine;
using TaleWorlds.MountAndBlade;
using static System.Reflection.BindingFlags;
Expand All @@ -12,21 +13,21 @@
namespace CommunityPatch.Patches.Perks.Endurance.Riding {

public sealed class TramplerPatch2 : PerkPatchBase<TramplerPatch2> {

public override bool Applied { get; protected set; }

private static readonly MethodInfo OverloadedTargetMethodInfo = typeof(Mission).GetMethod("GetAttackCollisionResults", Public | Static | DeclaredOnly);

private static readonly Type AttackInformationType = Type.GetType("AttackInformation");

private static readonly ConstructorInfo TargetConstructorInfo = typeof(AttackInformation).GetConstructor(new [] {
[CanBeNull]
private static readonly Type AttackInformationType = Type.GetType("TaleWorlds.MountAndBlade.AttackInformation, TaleWorlds.MountAndBlade, Version=1.0.0.0, Culture=neutral", false);

private static readonly ConstructorInfo TargetConstructorInfo = AttackInformationType?.GetConstructor(new[] {
typeof(Agent), typeof(Agent), typeof(GameEntity), typeof(AttackCollisionData).MakeByRefType()
});

private static readonly MethodInfo UpdateCharacterPostfixPatchMethodInfo = typeof(TramplerPatch2).
GetMethod(nameof(UpdateCorrectCharacterForHorseChargeDamagePostfix), NonPublic | Static | DeclaredOnly);
private static readonly MethodInfo UpdateCharacterPostfixPatchMethodInfo = typeof(TramplerPatch2).GetMethod(nameof(UpdateCorrectCharacterForHorseChargeDamagePostfix), NonPublic | Static | DeclaredOnly);

private static readonly MethodInfo UpdateHorseDamagePostfixPatchMethodInfo = typeof(TramplerPatch2).
GetMethod(nameof(UpdateHorseDamagePostfix), NonPublic | Static | DeclaredOnly);
private static readonly MethodInfo UpdateHorseDamagePostfixPatchMethodInfo = typeof(TramplerPatch2).GetMethod(nameof(UpdateHorseDamagePostfix), NonPublic | Static | DeclaredOnly);

public override IEnumerable<MethodBase> GetMethodsChecked() {
yield return TargetConstructorInfo;
Expand All @@ -42,7 +43,7 @@ public override IEnumerable<MethodBase> GetMethodsChecked() {
0x90, 0x4E, 0x8B, 0x8C, 0x14, 0xB1, 0xE6, 0xC7
}
};

public static readonly byte[][] ConstructorHashes = {
new byte[] {
// e1.4.0.228616
Expand All @@ -57,19 +58,18 @@ public TramplerPatch2() : base("GKlmIYik") {
}

public override bool? IsApplicable(Game game) {

if (OverloadedTargetMethodInfo == null)
return false;

if (AlreadyPatchedByOthers(Harmony.GetPatchInfo(OverloadedTargetMethodInfo)))
return false;

if (!OverloadedTargetMethodInfo.MakeCilSignatureSha256().MatchesAnySha256(OverloadedTargetHashes))
return false;

if (TargetConstructorInfo == null)
return false;

if (AlreadyPatchedByOthers(Harmony.GetPatchInfo(TargetConstructorInfo)))
return false;

Expand All @@ -82,30 +82,26 @@ public TramplerPatch2() : base("GKlmIYik") {
public override void Apply(Game game) {
if (Applied) return;

CommunityPatchSubModule.Harmony.Patch(TargetConstructorInfo,
postfix: new HarmonyMethod(UpdateCharacterPostfixPatchMethodInfo));
CommunityPatchSubModule.Harmony.Patch(TargetConstructorInfo,
postfix: new HarmonyMethod(UpdateCharacterPostfixPatchMethodInfo));

CommunityPatchSubModule.Harmony.Patch(OverloadedTargetMethodInfo,
postfix: new HarmonyMethod(UpdateHorseDamagePostfixPatchMethodInfo));
CommunityPatchSubModule.Harmony.Patch(OverloadedTargetMethodInfo,
postfix: new HarmonyMethod(UpdateHorseDamagePostfixPatchMethodInfo));

Applied = true;
}

private static readonly FieldInfo AttackerAgentCharacterFieldInfo = typeof(AttackInformation)
.GetField(nameof(AttackInformation.AttackerAgentCharacter), Public | Instance | DeclaredOnly);

private static void SetAttackerAgentCharacter(ref AttackInformation attackInformation, BasicCharacterObject attackerCharacter) {
object boxed = attackInformation;
AttackerAgentCharacterFieldInfo.SetValue(boxed, attackerCharacter);
attackInformation = (AttackInformation) boxed;
}

private static void UpdateCorrectCharacterForHorseChargeDamagePostfix(ref AttackInformation __instance, Agent attackerAgent, ref AttackCollisionData attackCollisionData) {
if (attackCollisionData.IsHorseCharge && attackerAgent.RiderAgent?.Character != null) {
SetAttackerAgentCharacter(ref __instance, attackerAgent.RiderAgent.Character);
}

private static readonly FieldInfo AttackerAgentCharacterFieldInfo = AttackInformationType?.GetField("AttackerAgentCharacter", Public | Instance | DeclaredOnly);

[CanBeNull]
private static readonly AccessTools.FieldRef<object, BasicCharacterObject> AttackerAgentCharacter
= AttackerAgentCharacterFieldInfo == null ? null : AccessTools.FieldRefAccess<object, BasicCharacterObject>(AttackerAgentCharacterFieldInfo);

private static void UpdateCorrectCharacterForHorseChargeDamagePostfix(ref object __instance, Agent attackerAgent, ref AttackCollisionData attackCollisionData) {
if (attackCollisionData.IsHorseCharge && attackerAgent.RiderAgent?.Character != null)
AttackerAgentCharacter!(__instance) = attackerAgent.RiderAgent.Character;
}

private static bool HeroHasPerk(BasicCharacterObject character, PerkObject perk)
=> (character as CharacterObject)?.GetPerkValue(perk) ?? false;

Expand All @@ -114,14 +110,15 @@ private int TramplerDamageModifier(int baseDamage) {
return (int) Math.Round(tramplerDamage, MidpointRounding.AwayFromZero);
}

private static void UpdateHorseDamagePostfix(ref AttackInformation attackInformation, ref AttackCollisionData attackCollisionData, ref CombatLogData combatLog) {
if (!(attackCollisionData.IsHorseCharge && HeroHasPerk(attackInformation.AttackerAgentCharacter, ActivePatch.Perk))) {
private static void UpdateHorseDamagePostfix(ref object attackInformation, ref AttackCollisionData attackCollisionData, ref CombatLogData combatLog) {
if (!(attackCollisionData.IsHorseCharge && HeroHasPerk(AttackerAgentCharacter!(attackInformation), ActivePatch.Perk))) {
return;
}

combatLog.InflictedDamage = ActivePatch.TramplerDamageModifier(combatLog.InflictedDamage);
attackCollisionData.InflictedDamage = ActivePatch.TramplerDamageModifier(attackCollisionData.InflictedDamage);
}

}

}
5 changes: 3 additions & 2 deletions tools/Antijank.Debugger/DebuggerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ private void Start()
public static ICorDebugProcess? DebugProcess;

[ThreadStatic]
public static ICLRRuntimeInfo ClrRuntime;
public static ICLRRuntimeInfo? ClrRuntime;

[ThreadStatic]
public static ICorProfilerInfo? ProfilerInfo;

public static int ThreadId;

public static readonly MethodInfo TestEnCMethod = typeof(DebuggerContext).GetMethod(nameof(TestEnC), DeclaredOnly | Public | Static);
//public static readonly MethodInfo TestEnCMethod = typeof(DebuggerContext).GetMethod(nameof(TestEnC), DeclaredOnly | Public | Static);

public static bool TestEnC() => false;

Expand Down Expand Up @@ -203,6 +203,7 @@ out var flags
*/
}

// debugger loop
foreach (var callback in _executionQueue.GetConsumingEnumerable()) {
try {
callback();
Expand Down
79 changes: 57 additions & 22 deletions tools/Antijank/MbObjectManagerPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,60 @@
using System.Runtime.CompilerServices;
using System.Xml;
using HarmonyLib;
using TaleWorlds.ObjectSystem;
using static System.Reflection.BindingFlags;

namespace Antijank {

public static class MbObjectManagerPatch {

private static int InitCount = 0;
private static readonly Type MbObjectMgrType
= Type.GetType("TaleWorlds.ObjectSystem.MBObjectManager, TaleWorlds.ObjectSystem, Version=1.0.0.0, Culture=neutral", false)
?? Type.GetType("TaleWorlds.Core.MBObjectManager, TaleWorlds.Core, Version=1.0.0.0, Culture=neutral", true);

private static readonly Type MbObjectBaseType
= Type.GetType("TaleWorlds.ObjectSystem.MBObjectBase, TaleWorlds.ObjectSystem, Version=1.0.0.0, Culture=neutral", false)
?? Type.GetType("TaleWorlds.Core.MBObjectBase, TaleWorlds.Core, Version=1.0.0.0, Culture=neutral", true);


private static readonly Type ObjTypeRecType = MbObjectMgrType.GetNestedType("IObjectTypeRecord", NonPublic | Instance | Static);

private static readonly MethodInfo ObjTypeRecElementListNameMethod = AccessTools.PropertyGetter(ObjTypeRecType, "ElementListName");

private static readonly MethodInfo ObjTypeRecElementNameMethod = AccessTools.PropertyGetter(ObjTypeRecType, "ElementName");

//private static string ObjTypeRecElementListName(object otr) => (string) ObjTypeRecElementListNameMethod.Invoke(otr, null);
private static readonly Func<object, string> ObjTypeRecElementListName
= ObjTypeRecElementListNameMethod.BuildInvoker<Func<object, string>>();

//private static string ObjTypeRecElementName(object otr) => (string) ObjTypeRecElementNameMethod.Invoke(otr, null);
private static readonly Func<object, string> ObjTypeRecElementName
= ObjTypeRecElementNameMethod.BuildInvoker<Func<object, string>>();

private static readonly MethodInfo MbObjectManagerGetPresumedObjectMethod = AccessTools.Method(MbObjectMgrType, "GetPresumedObject");

private static readonly MethodInfo MbObjectBaseDeserializeMethod1
= MbObjectBaseType.GetMethod("Deserialize", Public | NonPublic | Instance | DeclaredOnly, null, new[] {MbObjectMgrType, typeof(XmlNode)}, null);

private static readonly MethodInfo MbObjectBaseDeserializeMethod2
= MbObjectBaseType.GetMethod("Deserialize", Public | NonPublic | Instance | DeclaredOnly, null, new[] {MbObjectMgrType, typeof(XmlNode), typeof(Type)}, null);

private static readonly MethodInfo MbObjectBaseAfterInitializedMethod
= MbObjectBaseType.GetMethod("AfterInitialized", Public | NonPublic | Instance | DeclaredOnly);

private static readonly Action<object, object, XmlNode> MbObjectBaseDeserialize1
= MbObjectBaseDeserializeMethod1.BuildInvoker<Action<object, object, XmlNode>>();

private static readonly Action<object, object, XmlNode, Type> MbObjectBaseDeserialize2
= MbObjectBaseDeserializeMethod2.BuildInvoker<Action<object, object, XmlNode, Type>>();

private static readonly Action<object> MbObjectBaseAfterInitialized
= MbObjectBaseAfterInitializedMethod.BuildInvoker<Action<object>>();

private static readonly Func<object, string, string, bool, object> MbObjectManagerGetPresumedObject
= MbObjectManagerGetPresumedObjectMethod.BuildInvoker<Func<object, string, string, bool, object>>();

private static int InitCount = 0;

static MbObjectManagerPatch() {
if (InitCount > 0) {
if (Debugger.IsAttached)
Expand All @@ -24,11 +69,12 @@ static MbObjectManagerPatch() {
}

++InitCount;
Context.Harmony.Patch(AccessTools.Method(typeof(MBObjectManager), "CreateDocumentFromXmlFile"),

Context.Harmony.Patch(AccessTools.Method(MbObjectMgrType, "CreateDocumentFromXmlFile"),
postfix: new HarmonyMethod(typeof(MbObjectManagerPatch), nameof(CreateDocumentFromXmlFilePostfix)));
Context.Harmony.Patch(AccessTools.Method(typeof(MBObjectManager), "MergeTwoXmls"),
Context.Harmony.Patch(AccessTools.Method(MbObjectMgrType, "MergeTwoXmls"),
new HarmonyMethod(typeof(MbObjectManagerPatch), nameof(MergeTwoXmlsReplacement)));
Context.Harmony.Patch(AccessTools.Method(typeof(MBObjectManager), "LoadXml"),
Context.Harmony.Patch(AccessTools.Method(MbObjectMgrType, "LoadXml"),
new HarmonyMethod(typeof(MbObjectManagerPatch), nameof(LoadXmlReplacement)));
}

Expand Down Expand Up @@ -98,24 +144,12 @@ private static bool MergeTwoXmlsReplacement(ref XmlDocument __result, XmlDocumen
return false;
}

private static readonly Type ObjTypeRecType = typeof(MBObjectManager).GetNestedType("IObjectTypeRecord", NonPublic | Instance | Static);

private static readonly MethodInfo ObjTypeRecElementListNameMethod = AccessTools.PropertyGetter(ObjTypeRecType, "ElementListName");

private static readonly MethodInfo ObjTypeRecElementNameMethod = AccessTools.PropertyGetter(ObjTypeRecType, "ElementName");

private static readonly MethodInfo MbObjectManagerGetPresumedObjectMethod = AccessTools.Method(typeof(MBObjectManager), "GetPresumedObject");

private static string ObjTypeRecElementListName(object otr) => (string) ObjTypeRecElementListNameMethod.Invoke(otr, null);

private static string ObjTypeRecElementName(object otr) => (string) ObjTypeRecElementNameMethod.Invoke(otr, null);

private static readonly Dictionary<string, bool> ContinueWithErrorRememberChoice = new Dictionary<string, bool>();

private static readonly string AntijankXmlNamespace = "https://antijank/";

[MethodImpl(MethodImplOptions.NoInlining)]
private static bool LoadXmlReplacement(MBObjectManager __instance, IList ___ObjectTypeRecords, IList ___NonSerializedObjectTypeRecords, XmlDocument doc, Type typeOfGameMenusCallbacks) {
private static bool LoadXmlReplacement(object __instance, IList ___ObjectTypeRecords, IList ___NonSerializedObjectTypeRecords, XmlDocument doc, Type typeOfGameMenusCallbacks) {
var nodeIndex = 0;
var found = false;
string typeName = null;
Expand Down Expand Up @@ -157,12 +191,13 @@ private static bool LoadXmlReplacement(MBObjectManager __instance, IList ___Obje

var id = elem.GetAttribute("id");
try {
var obj = (MBObjectBase) MbObjectManagerGetPresumedObjectMethod.Invoke(__instance, new object[] {typeName, id, true});
// (MBObjectBase)
var obj = MbObjectManagerGetPresumedObject(__instance, typeName, id, true);
if (typeOfGameMenusCallbacks != null)
obj.Deserialize(__instance, node, typeOfGameMenusCallbacks);
MbObjectBaseDeserialize2(obj, __instance, node, typeOfGameMenusCallbacks);
else
obj.Deserialize(__instance, node);
obj.AfterInitialized();
MbObjectBaseDeserialize1(obj, __instance, node);
MbObjectBaseAfterInitialized(obj);
}
catch (Exception ex) {
var source = elem.GetAttribute("source", AntijankXmlNamespace);
Expand Down
7 changes: 5 additions & 2 deletions tools/Antijank/MemoryCleanupPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@ static MemoryCleanupPatch() {
Context.Harmony.Patch(AccessTools.Method(typeof(Managed), "GarbageCollect"),
new HarmonyMethod(typeof(MemoryCleanupPatch), nameof(MemoryCleanupReplacement)));

Context.Harmony.Patch(AccessTools.Method(Type.GetType("TaleWorlds.SaveSystem.Load.LoadCallbackInitializator, TaleWorlds.SaveSystem, Version=1.0.0.0, Culture=neutral"), "InitializeObjects"),
transpiler: new HarmonyMethod(typeof(MemoryCleanupPatch), nameof(GcCallsTranspiler)));
var loadCallbackInit = Type.GetType("TaleWorlds.SaveSystem.Load.LoadCallbackInitializator, TaleWorlds.SaveSystem, Version=1.0.0.0, Culture=neutral", false);
if (loadCallbackInit != null) {
var initObjs = AccessTools.Method(loadCallbackInit, "InitializeObjects");
Context.Harmony.Patch(initObjs, transpiler: new HarmonyMethod(typeof(MemoryCleanupPatch), nameof(GcCallsTranspiler)));
}

Context.Harmony.Patch(AccessTools.Method(typeof(LoadContext), nameof(LoadContext.Load)),
transpiler: new HarmonyMethod(typeof(MemoryCleanupPatch), nameof(GcCallsTranspiler)));
Expand Down

0 comments on commit 3984daa

Please sign in to comment.