Skip to content

Commit edf7c29

Browse files
committed
Documentation tweaks
1 parent acca68c commit edf7c29

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

src/DashStates/DreamTunnelDash/DreamTunnelDash.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ private static void NaiveMoveTowardsY(Player player, float targetY, float maxAmo
429429
player.NaiveMove(Vector2.UnitY * moveY);
430430
}
431431

432-
// Utilities to patch any method that checks the player's State
432+
// Utilities to patch any method that checks the player's State.
433433
/// <summary>
434434
/// Use if decompilation says <c>State==9</c>.
435435
/// </summary>
@@ -440,17 +440,19 @@ private static void NaiveMoveTowardsY(Player player, float targetY, float maxAmo
440440
private static readonly ILContext.Manipulator State_DreamDashNotEqual = il => CheckState(new ILCursor(il), Player.StDreamDash, false);
441441

442442
/// <summary>
443-
/// Patch any method that checks the player's state.
443+
/// Patch any method that checks the player's State.
444444
/// </summary>
445-
/// <remarks>Checks for <c>ldc.i4.s &lt;state&gt;</c></remarks>
445+
/// <remarks>Checks for <c>ldc.i4.s &lt;state&gt;</c>.</remarks>
446446
/// <param name="cursor">The ILCursor to use</param>
447447
/// <param name="state">The state to check for</param>
448-
/// <param name="equal">Whether the decompilation says <c>State == &lt;state&gt;</c></param>
448+
/// <param name="equal">Whether to check for <c>== &lt;state&gt;</c> or <c>!= &lt;state&gt;</c></param>
449449
private static void CheckState(ILCursor cursor, int state, bool equal)
450450
{
451451
// essentially, we want to perform these conversions:
452-
// `player.StateMachine.State == state` -> `player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash`
453-
// `player.StateMachine.State != state` -> `player.StateMachine.State != state && player.StateMachine.State != St.DreamTunnelDash`
452+
// - `player.StateMachine.State == <state>` -> `player.StateMachine.State == St.DreamTunnelDash || player.StateMachine.State == <state>`
453+
// - `player.StateMachine.State != <state>` -> `player.StateMachine.State != St.DreamTunnelDash && player.StateMachine.State != <state>`
454+
// the dream tunnel dash check comes before the normal check because 1. it's more predictable to implement and 2. vanilla has no state checks
455+
// that cause side effects and would thus be broken by our short-circuiting method.
454456

455457
// go to before the state check
456458
if (!cursor.TryGotoNextFirstFitReversed(MoveType.AfterLabel, 0x10,
@@ -459,48 +461,50 @@ private static void CheckState(ILCursor cursor, int state, bool equal)
459461
instr => instr.MatchLdcI4(state)))
460462
return;
461463

462-
// variables to grab various things
463464
bool matchedBeqOrBne = false, matchedCeq = false;
464465
ILLabel failedCheck = null;
465466
Instruction ceqInstr = null;
466467

467-
// retrieve the instruction after the current check
468+
// retrieve info about the current check
468469
ILCursor cloned = cursor.Clone();
469470
if (!cloned.TryGotoNext(MoveType.After, instr =>
470471
{
471472
// we grab a lot of stuff here: whether we matched a beq/bne.un or a ceq, the "fail state" label of the beq/bne.un
472473
// (if we matched one of those) and the actual ceq instruction (if we matched that).
473474

474-
// equality checks usually use bne.un (for ==) or beq (for !=) in order to branch past the block of the if statement if the values don't match
475+
// equality checks usually use bne.un (for ==) or beq (for !=) to branch past the block of the if statement when the values don't match
475476
matchedBeqOrBne = equal ? instr.MatchBneUn(out failedCheck) : instr.MatchBeq(out failedCheck);
477+
// alternatively they could use ceq and then a brtrue/brfalse to do the same, though i don't think there are any for this purpose in vanilla
476478
matchedCeq = (ceqInstr = instr).MatchCeq();
479+
477480
return matchedBeqOrBne || matchedCeq;
478481
})) return;
482+
// and the instruction after the current check
479483
Instruction afterMatch = cloned.Next!;
480484

481485
// beq and bne.un work with labels, whereas ceq just leaves a bool so we need to deal with them differently
482486
if (matchedBeqOrBne)
483487
{
484-
// labels for cleaning up duplicate player on stack
488+
// labels for cleaning up duplicate player left on stack
485489
ILLabel cleanUpPlayer = cursor.DefineLabel(), pastCleanUpPlayer = cursor.DefineLabel();
486490

487491
// duplicate player on stack
488492
cursor.Emit(OpCodes.Dup);
489-
// check if player is dream tunnel dashing and if so, short-circuit (while also cleaning up the other, now unnecessary duplicate player)
493+
// check if player is dream tunnel dashing and if so, short-circuit (while also popping the other, now unnecessary duplicate player off the stack)
490494
cursor.EmitDelegate<Func<Player, bool>>(player => player.StateMachine.State == St.DreamTunnelDash);
491495
cursor.Emit(OpCodes.Brtrue, cleanUpPlayer);
492496
// else, continue with check as normal
493497

494498
// where we short-circuit to depends on whether we check for equality or not.
495-
// for equality, we should short-circuit to the "block of the if statement" (past our current condition, whether it be the actual block or another condition),
496-
// since our desired behaviour is `player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash` and the first part of that or has been satisfied,
499+
// for equality, we should short-circuit to the "block" of the if statement (past our current condition, whether it be the actual block or another condition),
500+
// since our desired behaviour is `player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash` and the first term of that or has been satisfied,
497501
// just like how `if (true || condition()) { ... }` should immediately skip checking `condition()` (since `true` or anything is `true`) and run the block inside the if.
498-
// for inequality, it's the other way around: we should short-circuit immediately past the rest of the if statement, since our desired behaviour will be
502+
// for inequality, it's the other way around: we should short-circuit past the rest of the if statement (skipping the block), since our desired behaviour will be
499503
// `player.StateMachine.State != state && player.StateMachine.State != St.DreamTunnelDash` and we know the first condition of that and is false, just like how
500504
// `if (false && condition()) { ... }` should immediately skip checking `condition()` (since `false` and anything is `false`) and never run the block inside the if.
501505
// our `afterMatch` label points to after our current condition, and our `failedCheck` label points to after the rest of the statement.
502506
cursor.Goto(equal ? afterMatch : failedCheck.Target);
503-
// extra player cleanup, we branch over it in normal behaviour but jump into it if needed (see above)
507+
// extra player cleanup, we skip over it in normal behaviour but jump into it if needed (see above)
504508
cursor.Emit(OpCodes.Br, pastCleanUpPlayer);
505509
cursor.Emit(OpCodes.Pop);
506510
cursor.MarkLabel(pastCleanUpPlayer);

0 commit comments

Comments
 (0)