Skip to content

Commit

Permalink
Add support for UniTask to CoroutineUtils.GetMoveNext and PatchMoveNext
Browse files Browse the repository at this point in the history
  • Loading branch information
ManlyMarco committed Oct 7, 2021
1 parent 379501b commit 0c1443c
Showing 1 changed file with 26 additions and 8 deletions.
34 changes: 26 additions & 8 deletions src/Shared.Core/Utilities/CoroutineUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,22 +185,40 @@ public static IEnumerator PreventFromCrashing(this IEnumerator coroutine)
}

/// <summary>
/// Find the compiler-generated MoveNext method that contains the coroutine code. It can be used to apply transpliers to coroutines.
/// Note: When writing transpliers for coroutines you might want to turn off the "Decompiler\DecoDecompile enumerators" setting in DnSpy so that you can see the real code.
/// Find the compiler-generated MoveNext method that contains the Coroutine/UniTask code. It can be used to apply transpliers to Coroutines and UniTasks.
/// Note: When writing transpliers for coroutines you might want to turn off the "Decompiler\Decompile enumerators" setting in DnSpy so that you can see the real code.
/// UniTasks are considered "async/await" so you need to turn off the "Decompile async methods" setting instead.
/// </summary>
public static MethodInfo GetMoveNext(MethodBase targetMethod)
{
var ctx = new ILContext(new DynamicMethodDefinition(targetMethod).Definition);
var il = new ILCursor(ctx);
MethodReference enumeratorCtor = null;
il.GotoNext(instruction => instruction.MatchNewobj(out enumeratorCtor));
if (enumeratorCtor == null) throw new ArgumentNullException(nameof(enumeratorCtor));
if (enumeratorCtor.Name != ".ctor")
throw new ArgumentException($"Unexpected method name {enumeratorCtor.Name}, should be .ctor", nameof(enumeratorCtor));

var enumeratorType = enumeratorCtor.DeclaringType.ResolveReflection();
Type enumeratorType;
#if !PH && !KK
if (il.Method.ReturnType.Name == "UniTask")
{
enumeratorType = il.Body.Variables[0].VariableType.ResolveReflection();
if (!enumeratorType.Name.Contains(targetMethod.Name))
throw new ArgumentException($"Unexpected type name {enumeratorType.Name}, should contain {targetMethod.Name}");
}
else
#endif
{
MethodReference enumeratorCtor = null;
il.GotoNext(instruction => instruction.MatchNewobj(out enumeratorCtor));
if (enumeratorCtor == null) throw new ArgumentNullException(nameof(enumeratorCtor));
if (enumeratorCtor.Name != ".ctor")
throw new ArgumentException($"Unexpected method name {enumeratorCtor.Name}, should be .ctor", nameof(enumeratorCtor));

enumeratorType = enumeratorCtor.DeclaringType.ResolveReflection();
}

var movenext = enumeratorType.GetMethod("MoveNext", AccessTools.all);
if (movenext == null) throw new ArgumentNullException(nameof(movenext));

KoikatuAPI.Logger.LogDebug($"GetMoveNext found [{movenext.FullDescription()}] for [{targetMethod.FullDescription()}]");

return movenext;
}

Expand Down

0 comments on commit 0c1443c

Please sign in to comment.