差分
このページの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のない方を使えばいいと思います。\\ | ||