qstbak/LLib/LLib.Movement.Unstuck/RecoveryLadder.cs
2026-08-17 20:27:25 +10:00

241 lines
5.2 KiB
C#

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<string> _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<IRecoveryRung> rungs)
{
_003Coptions_003EP = options;
_rungs = rungs.ToArray();
_lastRunMs = new long[rungs.Count];
_hasRun = new bool[rungs.Count];
_rungsFired = new List<string>();
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;
}
}
}
}
}