Vectorial1024/EliteBionicsFramework

Compatibility with Vanilla Psycasts Expanded

Closed this issue · 8 comments

Steam user found incompatibility between EBF and Vanilla Psycasts Expanded (VPE), but self-made a patch between EBF and VPE, and has shared it out with me:

https://gist.github.com/delmain/2527f53f66053303a54023964e2b2729

Of course compatibility is one thing, but the other thing observed is the use of CodeMatcher from HarmonyLib itself, which seems very interesting...

When you say the use of CodeMatcher is interesting, what exactly do you mean? CodeMatcher is just a part of Harmony's public tool set that I have found to be a convenient way to write transpilers, so that you don't have to use foreach and yield return all over the place. The various Match methods along with the ability to insert, remove, and replace MSIL instructions is pretty nice. I guess if someone told me that it was slightly slower than using a yield return solution, I would believe them, but I don't think that transpilers which run once at game startup are a huge source of regular lag.

I have noticed, from looking at other mods' transpilers that very few people use it, is there a reason for that that I have not been made aware of? I have made extensive use of CodeMatcher in my local mods to tweak things and I have never run into a problem with it.

And as to your last comment on steam, a shout out in the commit message would be perfectly fine, I'd really appreciate it!

Well yes, in terms of functionality, supposedly CodeMatcher should work the same as manually making a transpiler, and in terms of performance, indeed no one gives any fucks because well, transpilation runs exactly once at startup and the runtime will not look at how its program codes are made anyway.

IMO why CodeMatcher is interesting is as follows:

It offers me a new way to look at things. You know, to make manual transpilers, I will have to look at the decompiled source, and count carefully which callvirt to swap out, and if I got it wrong, the patch fails. This means supposedly, I will have to recheck the compatibility everytime some mods pushed an update, to update the callvirt count. But if I use CodeMatcher, it seems I can just think about the pattern, and in most of the cases, the pattern is still there and I have less things to check.

Also, you do know HarmonyLib is currently at v2, right? A lot of modders (me included) made transpilers when it was still HarmonyLib v1, and I am pretty sure there was no such CodeMatcher back then. You know, documentations were lacking, and people found out "hey, the transpiler works like this", and so eventually others came in and copied code for their own use. And eventually there are a lot of hand-crafted transpilers out in the wild.

That makes 100% sense. I only started writing mods again recently. I modded fairly extensively in Beta, before Harmony existed, and I found the ability to stop using Unity Coroutines amazing so yeah, I get you. I wrote a Twitch chat integration that operated entirely out of Tick methods and Coroutines and good lord, being able to use actual .NET is so much nicer.

And yes, CodeMatcher letting you go "Find me a pattern and replace it" is wonderful. The Harmony docs are still sparse, but the v2 documentation is pretty good now. Let me drop a few links I've used in getting up to speed with it:

https://harmony.pardeike.net/articles/patching.html
https://github.com/pardeike/Harmony/tree/master/Harmony/Tools

The code is actually fairly good at self-documenting because the methods (at least in V2, I can't speak to V1) are very consistently named.

And one final link, with the caveat that this is technically for a forked version of Harmony, but most of the CodeMatcher stuff is still there:

https://github.com/BepInEx/HarmonyX/wiki/Transpiler-helpers

Update: I had a look at the original code from VPE, and it seems they are dealing with missing body parts. Which means, we can actually have some easier patching: we can use the public static float GetMaxHealthUnmodified(BodyPartDef def, Pawn pawn) method instead, and the thing is finished.

Still, I can study how this CodeMatcher works.

Still, I think I now understand how this CodeMatcher works at a basic level.

Because I do not have Royalty DLC, perhaps you may want to test whether the patch works? The commit is at f2d15d9

I downloaded and tested, and you need to pass the instructions to CodeMatcher. I made the change locally and tested, and the transpiler worked, but you typo'd the method to call. You set it as GetBodyPartMaxHealthUnmodified instead of GetMaxHealthUnmodified, which was causing failures because it caused a Pawn to be interpreted as a BodyPartDef and... yeah.

Anyway, these are the required changes:

image

Ahhh... no wonder when I try to copy it for another transpiler patch, it just doesn't work...

Thanks for the heads up! Imma type the new code later.

Seeing that I have typed the patch code in the repo already, I will just mark this as done, so that the milestone progress can look nice.

Will release the update when the rest of the milestone is ready.