差分
このページの2つのバージョン間の差分を表示します。
次のリビジョン | 前のリビジョン | ||
appendix:harmonyがある時 [2024/12/18 14:47] fumble 作成 |
appendix:harmonyがある時 [2024/12/29 00:31] (現在) fumble |
||
---|---|---|---|
行 54: | 行 54: | ||
それぞれ渡すべきプロトタイプは | それぞれ渡すべきプロトタイプは | ||
+ | prefixはパッチを当てるものと同じもの。\\ | ||
+ | postfixはパッチを当てるものの戻り値を受け取る戻りに無しのもの。\\ | ||
+ | finalizerはExceptionを貰ってExceptionを返すもの。\\ | ||
+ | transpilerとilmanipulatorは以下の様なもの。\\ | ||
<code csharp> | <code csharp> | ||
static IEnumerable< | static IEnumerable< | ||
+ | static void ILManipulator(ILContext il, MethodBase original, ILLabel retLabel) | ||
+ | static void SomeOtherILManipulator(ILContext ctx, MethodBase orig) | ||
</ | </ | ||
+ | |||
+ | 渡すときはHarmonyMethod(MethodInfo method)の変換、つまりコンストラクターを呼んで変換させる。 | ||
+ | <code csharp> | ||
+ | var transpilermethod = typeof(トランスパイラーのあるクラス).GetMethod(トランスパイラーのメソッド名); | ||
+ | var transpiler = Activator.CreateInstance(typeHarmonyMethod, | ||
+ | </ | ||
+ | |||
+ | 問題が起こりそうなのはTranspilerとILManipulatorのパターンでCodeInstructionがHarmonyの中で、ILLabelがMonoMod.Cliの中で宣言されているので参照出来ない状況だと面倒になる。\\ | ||
+ | ※ILContextはMono.CecilなのでSybaris2/ | ||
+ | |||
+ | 特に面倒が起こりそうな Transpiler の実装方法を示す。 | ||
+ | <code csharp> | ||
+ | static object Transpiler(IEnumerable instructions) | ||
+ | { | ||
+ | var enumerator = instructions? | ||
+ | if (enumerator != null && enumerator.MoveNext()) | ||
+ | { | ||
+ | var type = enumerator.Current.GetType(); | ||
+ | var fldOpecode = type.GetField(" | ||
+ | var fldOperand = type.GetField(" | ||
+ | var newInstructions = Activator.CreateInstance(typeof(List<> | ||
+ | foreach (var instruction in instructions) | ||
+ | { | ||
+ | var opecode = fldOpecode.GetValue(instruction); | ||
+ | var operand = fldOperand.GetValue(instruction); | ||
+ | if (opecode.Equals(変えたいところのOpCode) && operand != null && operand.ToString() == 変えたいところのOperand) | ||
+ | newInstructions.Add(Activator.CreateInstance(type, | ||
+ | else | ||
+ | newInstructions.Add(instruction); | ||
+ | } | ||
+ | } | ||
+ | return newInstructions; | ||
+ | } | ||
+ | </ | ||
+ | 引数をIEnumerableで受けて戻り値をobjectとかで宣言してしまいます。\\ | ||
+ | 引数で貰った IEnumerable< | ||
+ | |||
+ | <code csharp> | ||
+ | var newInstructions = Activator.CreateInstance(typeof(List<> | ||
+ | return newInstructions; | ||
+ | </ | ||
+ | |||
+ | こんなのでいいの?って思うかもしれませんが多分これで良いのです。\\ | ||
+ | あとは変えたいところだけ、全部変えたいなら全部詰め直して返せば良いです。\\ | ||
+ | OpCodeはSystem.Reflection.Emit.OpCodeっぽいのでこれを参照すればHarmonyLibの参照はなしでいけます。\\ | ||
+ | ILManipulatorの方もILLabel retLabelをobjectで受けてリフレクションを使えばいけると思います、必要が無い限りILLabelのない方を使えばいいと思います。\\ | ||