using System.Collections.Generic; using System.Linq; namespace LLib.Movement.Unstuck; public sealed class RecoveryLadder { private readonly IRecoveryRung[] _rungs; private readonly long[] _lastRunMs; private readonly bool[] _hasRun; private readonly List _rungsFired; private bool _hasRunAny; private long _lastRunAnyMs; private long _firstStallMs; private long _lastStallMs; public int Attempts { get; private set; } public bool IsExhausted { get; private set; } private int Cap { get { RecoveryMode mode = _003Coptions_003EP.Mode; int num = ((mode == RecoveryMode.Aggressive) ? (-304547260) : (-304547257)); int result = default(int); while (true) { int num2 = num; int num3 = -304547258; int num4 = num2; switch ((num4 | num3) - (num4 & num3)) { case 4: result = _003Coptions_003EP.PassiveCap; num = -304547258; break; case 1: num = ((mode == RecoveryMode.Passive) ? (-304547262) : (-304547264)); break; case 6: num = -304547261; break; case 2: result = _003Coptions_003EP.AggressiveCap; num = -304547258; break; case 5: result = _003Coptions_003EP.ConservativeCap; num = -304547258; break; case 3: num = -304547257; break; case 0: return result; } } } } public RecoveryLadder(RecoveryLadderOptions options, IReadOnlyList rungs) { _003Coptions_003EP = options; _rungs = rungs.ToArray(); _lastRunMs = new long[rungs.Count]; _hasRun = new bool[rungs.Count]; _rungsFired = new List(); base._002Ector(); } public RecoveryDecision OnStall(long nowMs) { int num = ((!IsExhausted) ? 1754338781 : 1754338772); IRecoveryRung recoveryRung = default(IRecoveryRung); int num7 = default(int); while (true) { int num2 = num; int num3 = 1754338771; int num4 = num2; int num5 = num4 + num3; int num6 = num4 & num3; switch (num5 - (num6 + num6)) { case 9: { long num8 = _lastRunAnyMs; long num9 = nowMs; num = ((~(~num9 + num8) >= _003Coptions_003EP.GlobalCooldownMs) ? 1754338774 : 1754338768); break; } case 0: num = ((!_hasRunAny) ? 1754338774 : 1754338778); break; case 14: num = ((Attempts < Cap) ? 1754338771 : 1754338783); break; case 16: num = ((!recoveryRung.CanRun(Attempts + 1, nowMs)) ? 1754338773 : 1754338782); break; case 10: recoveryRung = _rungs[num7]; num = ((!_hasRun[num7]) ? 1754338755 : 1754338776); break; case 4: num = 1754338772; break; case 13: Consume(nowMs); _rungsFired.Add(recoveryRung.Name); _hasRun[num7] = true; _lastRunMs[num7] = nowMs; _hasRunAny = true; _lastRunAnyMs = nowMs; return new RecoveryDecision(RecoveryDecisionKind.Run, recoveryRung, null); case 6: { int num10 = num7; num3 = 1; num4 = num10; int num11 = num4 ^ num3; int num12 = num4 & num3; num7 = num11 + (num12 + num12); num = 1754338769; break; } case 12: IsExhausted = true; return new RecoveryDecision(RecoveryDecisionKind.Exhausted, null, new RecoveryExhaustion(Attempts, _rungsFired.ToArray(), _firstStallMs, _lastStallMs)); case 1: Consume(nowMs); return new RecoveryDecision(RecoveryDecisionKind.Observe, null, null); case 5: num = ((_003Coptions_003EP.Mode != RecoveryMode.Passive) ? 1754338779 : 1754338770); break; case 11: { long num8 = _lastRunMs[num7]; long num9 = nowMs; num = ((~(~num9 + num8) < recoveryRung.CooldownMs) ? 1754338773 : 1754338755); break; } case 3: return new RecoveryDecision(RecoveryDecisionKind.None, null, null); case 2: num = ((num7 < _rungs.Length) ? 1754338777 : 1754338780); break; case 15: return new RecoveryDecision(RecoveryDecisionKind.None, null, null); case 7: return new RecoveryDecision(RecoveryDecisionKind.None, null, null); case 8: num7 = 0; num = 1754338769; break; } } } public void Reset() { Attempts = 0; IsExhausted = false; _rungsFired.Clear(); _hasRunAny = false; int num = 0; int num2 = -478483629; while (true) { int num3 = num2; int num4 = -478483631; int num5 = num3; int num6 = num5 + num4; int num7 = num5 & num4; switch (num6 - (num7 + num7)) { case 0: return; case 2: num2 = ((num < _hasRun.Length) ? (-478483632) : (-478483631)); break; case 1: { _hasRun[num] = false; int num8 = num; num4 = 1; num5 = num8; int num9 = num5 ^ num4; int num10 = num5 & num4; num = num9 + (num10 + num10); num2 = -478483629; break; } case 3: num2 = -478483629; break; } } } private void Consume(long nowMs) { int num = ((Attempts != 0) ? 1659706856 : 1659706857); while (true) { int num2 = num; int num3 = 1659706856; int num4 = num2; int num5 = num4 + num3; int num6 = num4 & num3; switch (num5 - (num6 + num6)) { case 2: num = 1659706857; break; case 1: _firstStallMs = nowMs; num = 1659706856; break; case 0: { int attempts = Attempts; num3 = 1; num4 = attempts; Attempts = (num4 | num3) + (num4 & num3); _lastStallMs = nowMs; return; } } } } }