appendix:harmonyがある時

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

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