Skip to content

Commit

Permalink
Merge pull request #389 from WEGFan/fix/minitextbox
Browse files Browse the repository at this point in the history
  • Loading branch information
0x0ade authored Oct 14, 2021
2 parents 3c8b006 + af602a6 commit fa53631
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
63 changes: 63 additions & 0 deletions Celeste.Mod.mm/MonoModRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,12 @@ class PatchPlayerBeforeUpTransition : Attribute { }
[MonoModCustomMethodAttribute(nameof(MonoModRules.PatchDeathEffectUpdate))]
class PatchDeathEffectUpdateAttribute : Attribute { }

/// <summary>
/// Patches the method to fix mini textbox not closing when it's expanding and another textbox is triggered.
/// </summary>
[MonoModCustomMethodAttribute(nameof(MonoModRules.PatchMiniTextboxRoutine))]
class PatchMiniTextboxRoutine : Attribute { }

static class MonoModRules {

static bool IsCeleste;
Expand Down Expand Up @@ -2292,6 +2298,63 @@ public static void PatchDeathEffectUpdate(ILContext context, CustomAttribute att

}

/// <summary>
/// <inheritdoc cref="MonoMod.PatchMiniTextboxRoutine" />
/// </summary>
public static void PatchMiniTextboxRoutine(MethodDefinition method, CustomAttribute attrib) {
FieldDefinition f_MiniTextbox_closing = method.DeclaringType.FindField("closing");

// The routine is stored in a compiler-generated method.
foreach (TypeDefinition nest in method.DeclaringType.NestedTypes) {
if (!nest.Name.StartsWith("<" + method.Name + ">d__")) {
continue;
}
method = nest.FindMethod("System.Boolean MoveNext()") ?? method;
break;
}

new ILContext(method).Invoke(il => {
ILCursor cursor = new ILCursor(il);

/*
Change:
while ((this.ease += Engine.DeltaTime * 4f) < 1f)) {
continueLoopTarget:
yield return null;
}
this.ease = 1f;
to:
while ((this.ease += Engine.DeltaTime * 4f) < 1f)) {
continueLoopTarget:
if (this.closing) {
yield break;
}
yieldReturnNullTarget:
yield return null;
}
this.ease = 1f;
*/
ILLabel continueLoopTarget = cursor.DefineLabel();
cursor.GotoNext(MoveType.After,
instr => instr.MatchLdloc(6),
instr => instr.MatchLdcR4(1f),
instr => instr.MatchBlt(out continueLoopTarget));

cursor.Goto(continueLoopTarget.Target, MoveType.AfterLabel);

ILLabel yieldReturnNullTarget = cursor.DefineLabel();
cursor.Emit(OpCodes.Ldloc_1);
cursor.Emit(OpCodes.Ldfld, f_MiniTextbox_closing);
cursor.Emit(OpCodes.Brfalse, yieldReturnNullTarget);
cursor.Emit(OpCodes.Ldc_I4_0);
cursor.Emit(OpCodes.Ret);
cursor.MarkLabel(yieldReturnNullTarget);
});
}

public static void PostProcessor(MonoModder modder) {
// Patch CrushBlock::AttackSequence's first alarm delegate manually because how would you even annotate it?
PatchCrushBlockFirstAlarm(modder.Module.GetType("Celeste.CrushBlock/<>c__DisplayClass41_0").FindMethod("<AttackSequence>b__1"));
Expand Down
17 changes: 17 additions & 0 deletions Celeste.Mod.mm/Patches/MiniTextbox.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections;
using MonoMod;

namespace Celeste {
class patch_MiniTextbox : MiniTextbox {

public patch_MiniTextbox(string dialogId)
: base(dialogId) {
// no-op. MonoMod ignores this - we only need this to make the compiler shut up.
}

[MonoModIgnore]
[PatchMiniTextboxRoutine]
private extern IEnumerator Routine();

}
}

0 comments on commit fa53631

Please sign in to comment.