Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mini textbox not closing when it's expanding and another textbox is triggered #389

Merged
merged 1 commit into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();

}
}