using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NoMoreGettingOverIt")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+98b6daedc3f44362f9f296df7c6e93964c5ef007")]
[assembly: AssemblyProduct("NoMoreGettingOverIt")]
[assembly: AssemblyTitle("NoMoreGettingOverIt")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace NoMoreGettingOverIt
{
[BepInPlugin("com.iwan.nomoregettingoverit", "NoMoreGettingOverIt", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private class SaveState
{
public Vector3 Position { get; set; }
public Vector2 Velocity { get; set; }
public int Health { get; set; }
public int MaxHealth { get; set; }
public int Geo { get; set; }
public int Silk { get; set; }
public string SceneName { get; set; } = string.Empty;
public bool FacingRight { get; set; }
}
[CompilerGenerated]
private sealed class <>c__DisplayClass10_0
{
public SaveState savestate;
internal bool <LoadCrossSceneSaveState>b__0()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
return ((Scene)(ref activeScene)).name == savestate.SceneName;
}
}
[CompilerGenerated]
private sealed class <LoadCrossSceneSaveState>d__10 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public SaveState savestate;
public Plugin <>4__this;
private <>c__DisplayClass10_0 <>8__1;
private GameObject <heroGO>5__2;
private Rigidbody2D <rb>5__3;
private float <endTime>5__4;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadCrossSceneSaveState>d__10(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<heroGO>5__2 = null;
<rb>5__3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Expected O, but got Unknown
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
Plugin plugin = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>8__1 = new <>c__DisplayClass10_0();
<>8__1.savestate = savestate;
plugin._isRestoring = true;
Addressables.LoadSceneAsync((object)("Scenes/" + <>8__1.savestate.SceneName), (LoadSceneMode)0, true, 100, (SceneReleaseMode)0);
<>2__current = (object)new WaitUntil((Func<bool>)delegate
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
return ((Scene)(ref activeScene)).name == <>8__1.savestate.SceneName;
});
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
goto IL_00be;
case 2:
<>1__state = -1;
goto IL_00be;
case 3:
{
<>1__state = -1;
HeroController instance = HeroController.instance;
<heroGO>5__2 = ((Component)instance).gameObject;
<rb>5__3 = <heroGO>5__2.GetComponent<Rigidbody2D>();
PlayerData instance2 = PlayerData.instance;
instance2.health = <>8__1.savestate.Health;
instance2.maxHealth = <>8__1.savestate.MaxHealth;
instance2.geo = <>8__1.savestate.Geo;
instance2.silk = <>8__1.savestate.Silk;
if (instance.cState.facingRight != <>8__1.savestate.FacingRight)
{
instance.FlipSprite();
}
GameCameras instance3 = GameCameras.instance;
if ((Object)(object)instance3 != (Object)null && (Object)(object)instance3.cameraController != (Object)null)
{
instance3.cameraController.SnapTo(<>8__1.savestate.Position.x, <>8__1.savestate.Position.y);
}
<endTime>5__4 = Time.time + 0.6f;
break;
}
case 4:
{
<>1__state = -1;
break;
}
IL_00be:
if ((Object)(object)HeroController.instance == (Object)null)
{
<>2__current = null;
<>1__state = 2;
return true;
}
<>2__current = null;
<>1__state = 3;
return true;
}
if (Time.time < <endTime>5__4)
{
<heroGO>5__2.transform.position = <>8__1.savestate.Position;
if ((Object)(object)<rb>5__3 != (Object)null)
{
<rb>5__3.linearVelocity = Vector2.zero;
}
<>2__current = null;
<>1__state = 4;
return true;
}
if ((Object)(object)<rb>5__3 != (Object)null)
{
<rb>5__3.linearVelocity = <>8__1.savestate.Velocity;
}
((BaseUnityPlugin)plugin).Logger.LogInfo((object)$"Rewound to {<>8__1.savestate.SceneName}! ({plugin._savestates.Count} remaining)");
plugin._isRestoring = false;
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private ConfigEntry<KeyCode>? _rewindKey;
private ConfigEntry<float>? _saveInterval;
private ConfigEntry<int>? _maxSavestates;
private readonly List<SaveState> _savestates = new List<SaveState>();
private float _timer;
private bool _isRestoring;
private void Awake()
{
_rewindKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "RewindKey", (KeyCode)283, "Key to rewind to the previous savestate");
_saveInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "SaveInterval", 10f, "Interval in seconds between automatic savestates");
_maxSavestates = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "MaxSavestates", 12, "Maximum number of savestates to keep (12 = 2 minutes at 10s interval)");
((BaseUnityPlugin)this).Logger.LogInfo((object)"NoMoreGettingOverIt loaded! Press F2 to rewind.");
}
private void Update()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
if (_isRestoring)
{
return;
}
HeroController instance = HeroController.instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
if (Input.GetKeyDown(_rewindKey.Value))
{
LoadSaveState();
return;
}
_timer += Time.deltaTime;
if (_timer >= _saveInterval.Value)
{
_timer = 0f;
CreateSaveState(instance);
}
}
private void CreateSaveState(HeroController hero)
{
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
GameManager instance = GameManager.instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
PlayerData instance2 = PlayerData.instance;
if (instance2 != null && !instance.IsInSceneTransition && !hero.cState.dead && !hero.cState.transitioning)
{
GameObject gameObject = ((Component)hero).gameObject;
Rigidbody2D component = gameObject.GetComponent<Rigidbody2D>();
SaveState item = new SaveState
{
Position = gameObject.transform.position,
Velocity = (((Object)(object)component != (Object)null) ? component.linearVelocity : Vector2.zero),
Health = instance2.health,
MaxHealth = instance2.maxHealth,
Geo = instance2.geo,
Silk = instance2.silk,
SceneName = instance.GetSceneNameString(),
FacingRight = hero.cState.facingRight
};
_savestates.Add(item);
while (_savestates.Count > _maxSavestates.Value)
{
_savestates.RemoveAt(0);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Savestate created ({_savestates.Count}/{_maxSavestates.Value})");
}
}
private void LoadSaveState()
{
if (_savestates.Count == 0)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"No savestate available to load!");
return;
}
HeroController instance = HeroController.instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
GameManager instance2 = GameManager.instance;
if (!((Object)(object)instance2 == (Object)null))
{
List<SaveState> savestates = _savestates;
SaveState saveState = savestates[savestates.Count - 1];
_savestates.RemoveAt(_savestates.Count - 1);
_timer = 0f;
if (instance2.GetSceneNameString() != saveState.SceneName)
{
((MonoBehaviour)this).StartCoroutine(LoadCrossSceneSaveState(saveState));
}
else
{
RestoreSameSceneSaveState(saveState, instance);
}
}
}
[IteratorStateMachine(typeof(<LoadCrossSceneSaveState>d__10))]
private IEnumerator LoadCrossSceneSaveState(SaveState savestate)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadCrossSceneSaveState>d__10(0)
{
<>4__this = this,
savestate = savestate
};
}
private void RestoreSameSceneSaveState(SaveState savestate, HeroController hero)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
GameObject gameObject = ((Component)hero).gameObject;
gameObject.transform.position = savestate.Position;
Rigidbody2D component = gameObject.GetComponent<Rigidbody2D>();
if ((Object)(object)component != (Object)null)
{
component.linearVelocity = savestate.Velocity;
}
PlayerData instance = PlayerData.instance;
instance.health = savestate.Health;
instance.maxHealth = savestate.MaxHealth;
instance.geo = savestate.Geo;
instance.silk = savestate.Silk;
if (hero.cState.facingRight != savestate.FacingRight)
{
hero.FlipSprite();
}
GameCameras instance2 = GameCameras.instance;
if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.cameraController != (Object)null)
{
instance2.cameraController.SnapTo(savestate.Position.x, savestate.Position.y);
}
((BaseUnityPlugin)this).Logger.LogInfo((object)$"Rewound! ({_savestates.Count} remaining)");
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "com.iwan.nomoregettingoverit";
public const string PLUGIN_NAME = "NoMoreGettingOverIt";
public const string PLUGIN_VERSION = "1.0.0";
}
}