Decompiled source of PeglinQuickRestart v1.1.0

PeglinQuickRestart.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cruciball;
using HarmonyLib;
using Loading;
using Microsoft.CodeAnalysis;
using Peglin.ClassSystem;
using PeglinQuickRestart.Core;
using PeglinUI.LoadoutManager;
using PeglinUI.MainMenu;
using PeglinUI.MainMenu.Cruciball;
using Relics;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("PeglinQuickRestart")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+9d0e5c8cd1a8420e6dbe59e1dc2f8dd9ce57bea0")]
[assembly: AssemblyProduct("PeglinQuickRestart")]
[assembly: AssemblyTitle("PeglinQuickRestart")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 PeglinQuickRestart
{
	[BepInPlugin("PeglinQuickRestart", "PeglinQuickRestart", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "PeglinQuickRestart";

		public const string Name = "PeglinQuickRestart";

		public const string Version = "1.1.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyboardShortcut> RestartKey;

		internal static ConfigEntry<KeyboardShortcut> ControllerRestartButton;

		internal static ConfigEntry<float> HoldSeconds;

		internal static ConfigEntry<bool> ShowHoldProgress;

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			RestartKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "RestartKey", new KeyboardShortcut((KeyCode)120, Array.Empty<KeyCode>()), "Hold this key to abandon the current run and start a new one with the same class, Cruciball level and loadout. A run started with a custom seed restarts on that seed; any other run gets a new random seed.");
			ControllerRestartButton = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ControllerRestartButton", new KeyboardShortcut((KeyCode)338, Array.Empty<KeyCode>()), "Controller button to hold for a restart. Default JoystickButton8 is clicking the left stick (L3) on Xbox-layout controllers, including PlayStation and other pads when Steam Input is on. Set to None to disable.");
			HoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "HoldSeconds", 1.5f, "How long to hold the restart key, in real seconds (not affected by game speed or pause).");
			ShowHoldProgress = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHoldProgress", true, "Show a countdown at the top of the screen while the restart key is held.");
			new Harmony("PeglinQuickRestart").PatchAll(typeof(Plugin).Assembly);
			GameObject val = new GameObject("PeglinQuickRestart")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<RestartKeyWatcher>();
			Log.LogInfo((object)string.Format("{0} {1} loaded. Hold {2} or {3} for {4}s to restart the run.", "PeglinQuickRestart", "1.1.0", RestartKey.Value, ControllerRestartButton.Value, HoldSeconds.Value));
		}
	}
	internal class RestartKeyWatcher : MonoBehaviour
	{
		private HoldTimer _hold;

		private RunRestarter _restarter;

		private GUIStyle _style;

		private void Awake()
		{
			_hold = new HoldTimer(Plugin.HoldSeconds.Value);
			Plugin.HoldSeconds.SettingChanged += delegate
			{
				_hold = new HoldTimer(Plugin.HoldSeconds.Value);
			};
			_restarter = new RunRestarter((MonoBehaviour)(object)this);
		}

		private void Update()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			bool keyHeld = !_restarter.Busy && (IsHeld(Plugin.RestartKey.Value) || IsHeld(Plugin.ControllerRestartButton.Value)) && _restarter.InRestartableScene();
			if (_hold.Update(keyHeld, Time.unscaledDeltaTime))
			{
				_restarter.TryRestart();
			}
		}

		private static bool IsHeld(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0)
			{
				return ((KeyboardShortcut)(ref shortcut)).IsPressed();
			}
			return false;
		}

		private void OnGUI()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			string text = (_restarter.Busy ? "Restarting run..." : _restarter.Notice);
			if (text == null && Plugin.ShowHoldProgress.Value && _hold.Charging)
			{
				text = $"Hold to restart run: {Mathf.Max(0f, _hold.HoldSeconds - _hold.Held):0.0}s";
			}
			if (text != null)
			{
				if (_style == null)
				{
					_style = new GUIStyle(GUI.skin.box)
					{
						fontSize = 22,
						alignment = (TextAnchor)4
					};
				}
				GUI.Box(new Rect((float)Screen.width / 2f - 260f, 20f, 520f, 44f), text, _style);
			}
		}
	}
	internal sealed class RunRestarter
	{
		private const string MainMenuScene = "MainMenu";

		private const float SceneLoadTimeout = 30f;

		private const float MenuTimeout = 10f;

		private const float NoticeSeconds = 4f;

		private static readonly FieldRef<CharacterSelectController, List<SelectableCharacter>> AvailableCharacters = AccessTools.FieldRefAccess<CharacterSelectController, List<SelectableCharacter>>("_availableCharacters");

		private static readonly FieldRef<CharacterSelectController, bool> ClassesLoaded = AccessTools.FieldRefAccess<CharacterSelectController, bool>("_classesLoaded");

		private static readonly FieldRef<LoadoutManager, DeckManager> LoadoutDeckManager = AccessTools.FieldRefAccess<LoadoutManager, DeckManager>("_deckManager");

		private static readonly FieldRef<LoadoutManager, RelicManager> LoadoutRelicManager = AccessTools.FieldRefAccess<LoadoutManager, RelicManager>("_relicManager");

		private static readonly MethodInfo ChangeClass = AccessTools.Method(typeof(CharacterSelectController), "ChangeClass", new Type[1] { typeof(SelectableCharacter) }, (Type[])null);

		private readonly MonoBehaviour _host;

		private string _notice;

		private float _noticeUntil;

		internal bool Busy { get; private set; }

		internal string Notice
		{
			get
			{
				if (!(Time.unscaledTime < _noticeUntil))
				{
					return null;
				}
				return _notice;
			}
		}

		internal RunRestarter(MonoBehaviour host)
		{
			_host = host;
		}

		internal bool InRestartableScene()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			PeglinSceneLoader val = Object.FindObjectOfType<PeglinSceneLoader>();
			if ((Object)(object)val != (Object)null && !val.isLoading)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name != "MainMenu";
			}
			return false;
		}

		internal void TryRestart()
		{
			RunSetupRecord runSetupRecord = RunSetup.ForCurrentRun();
			if (runSetupRecord == null)
			{
				Show("Can't restart: this run's custom setup isn't known");
				Plugin.Log.LogWarning((object)"Can't restart: no run in progress, or a custom run started before the mod was installed.");
			}
			else if (!Enum.IsDefined(typeof(Class), runSetupRecord.Class))
			{
				Show("Can't restart: unknown class " + runSetupRecord.Class);
			}
			else
			{
				_host.StartCoroutine(Restart(runSetupRecord));
			}
		}

		private IEnumerator Restart(RunSetupRecord setup)
		{
			Busy = true;
			Plugin.Log.LogInfo((object)($"Restarting run: {setup.Class}, Cruciball {setup.CruciballLevel}, " + (setup.CustomSeed ? ("seed " + setup.Seed) : "random seed") + (setup.CustomLoadout ? ", custom loadout" : "") + "."));
			AbandonRun();
			float waited = 0f;
			PeglinSceneLoader val = Object.FindObjectOfType<PeglinSceneLoader>();
			while (true)
			{
				if (!((Object)(object)val == (Object)null) && !val.isLoading)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					if (!(((Scene)(ref activeScene)).name != "MainMenu"))
					{
						break;
					}
				}
				float num;
				waited = (num = waited + Time.unscaledDeltaTime);
				if (num > 30f)
				{
					Fail("the main menu didn't load");
					yield break;
				}
				yield return null;
				val = Object.FindObjectOfType<PeglinSceneLoader>();
			}
			PlayButton play = Object.FindObjectOfType<PlayButton>();
			if ((Object)(object)play == (Object)null)
			{
				Fail("couldn't find the Play button");
				yield break;
			}
			play.MovetoCharacterSelect();
			waited = 0f;
			LoadoutManager loadout;
			CharacterSelectController characters;
			CruciballLevelSelector cruciballSelector;
			while (true)
			{
				loadout = Object.FindObjectOfType<LoadoutManager>();
				characters = (((Object)(object)loadout != (Object)null) ? loadout.characterSelectController : null);
				cruciballSelector = Object.FindObjectOfType<CruciballLevelSelector>();
				if (((Component)play._characterSelectGroup).gameObject.activeInHierarchy && (Object)(object)loadout != (Object)null && (Object)(object)characters != (Object)null && ClassesLoaded.Invoke(characters) && (Object)(object)cruciballSelector != (Object)null)
				{
					break;
				}
				float num;
				waited = (num = waited + Time.unscaledDeltaTime);
				if (num > 10f)
				{
					Fail("the character select screen didn't open");
					yield break;
				}
				yield return null;
			}
			yield return null;
			string text = ApplySetup(setup, loadout, characters);
			if (text != null)
			{
				Fail(text);
				yield break;
			}
			if ((Object)(object)cruciballSelector.playButton != (Object)null && ((UnityEventBase)cruciballSelector.playButton.onClick).GetPersistentEventCount() > 0)
			{
				((UnityEvent)cruciballSelector.playButton.onClick).Invoke();
			}
			else
			{
				loadout.SetupDataForNewGame();
				play.ConfirmRunConfigAndStartGame();
			}
			Busy = false;
		}

		private static void AbandonRun()
		{
			PauseMenu val = Object.FindObjectOfType<PauseMenu>();
			if ((Object)(object)val != (Object)null)
			{
				val.AbandonRun();
				return;
			}
			if (!StaticGameData.hasReachedBoss)
			{
				PlayerPrefs.SetInt(GameInit.BOSS_STREAK_PREF_STRING, 0);
			}
			if (PauseMenu.Paused)
			{
				PauseMenu.Paused = false;
				PauseToggle onPauseToggled = PauseMenu.OnPauseToggled;
				if (onPauseToggled != null)
				{
					onPauseToggled.Invoke(false);
				}
			}
			SaveManager.RequestDelete();
			PeglinSceneLoader.Instance.LoadScene((Scene)1, (LoadSceneMode)0, false, 0.5f);
		}

		private static string ApplySetup(RunSetupRecord setup, LoadoutManager loadout, CharacterSelectController characters)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			Class cls = (Class)Enum.Parse(typeof(Class), setup.Class);
			SelectableCharacter val = ((IEnumerable<SelectableCharacter>)AvailableCharacters.Invoke(characters)).FirstOrDefault((Func<SelectableCharacter, bool>)((SelectableCharacter c) => c.characterClass == cls));
			if ((Object)(object)val == (Object)null || !val.IsUnlocked)
			{
				return setup.Class + " isn't available";
			}
			if (characters.currentlySelectedClass != cls)
			{
				ChangeClass.Invoke(characters, new object[1] { val });
			}
			if (characters.currentlySelectedClass != cls)
			{
				return "couldn't select " + setup.Class;
			}
			CruciballManager val2 = RunSetup.LoadoutCruciballManager.Invoke(loadout);
			if ((Object)(object)val2 != (Object)null && val2.currentCruciballLevel != setup.CruciballLevel)
			{
				val2.SetRunCruciballLevelAndClass(setup.CruciballLevel, cls);
			}
			if (setup.CustomLoadout)
			{
				DeckManager val3 = LoadoutDeckManager.Invoke(loadout);
				RelicManager val4 = LoadoutRelicManager.Invoke(loadout);
				List<GameObject> list = new List<GameObject>();
				foreach (string orb in setup.Orbs)
				{
					GameObject val5 = (((Object)(object)val3 != (Object)null) ? val3.GetOrbPrefabFromName(orb) : null);
					if ((Object)(object)val5 == (Object)null)
					{
						return "couldn't find starting orb " + orb;
					}
					list.Add(val5);
				}
				List<Relic> list2 = new List<Relic>();
				foreach (string relic in setup.Relics)
				{
					Relic val6 = (((Object)(object)val4 != (Object)null && Enum.IsDefined(typeof(RelicEffect), relic)) ? val4.GetRelicForEffectFromAllData((RelicEffect)Enum.Parse(typeof(RelicEffect), relic)) : null);
					if ((Object)(object)val6 == (Object)null)
					{
						return "couldn't find starting relic " + relic;
					}
					list2.Add(val6);
				}
				loadout.hasCustomLoadout = true;
				loadout.StartingOrbs.Clear();
				loadout.StartingOrbs.AddRange(list);
				loadout.StartingRelics.Clear();
				loadout.StartingRelics.AddRange(list2);
			}
			loadout.seedInputPopup.hasCustomSeed = setup.CustomSeed;
			StaticGameData.currentSeed = (setup.CustomSeed ? setup.Seed : string.Empty);
			return null;
		}

		private void Fail(string reason)
		{
			Busy = false;
			Show("Restart stopped: " + reason);
			Plugin.Log.LogWarning((object)("Restart stopped at the main menu: " + reason + "."));
		}

		private void Show(string message)
		{
			_notice = message;
			_noticeUntil = Time.unscaledTime + 4f;
		}
	}
	internal static class RunSetup
	{
		private static readonly string SavePath = Path.Combine(Paths.ConfigPath, "PeglinQuickRestart.lastrun.txt");

		internal static readonly FieldRef<LoadoutManager, CruciballManager> LoadoutCruciballManager = AccessTools.FieldRefAccess<LoadoutManager, CruciballManager>("_cruciballManager");

		internal static RunSetupRecord Pending;

		private static RunSetupRecord _current;

		internal static void RecordPlay(LoadoutManager loadout)
		{
			CruciballManager val = LoadoutCruciballManager.Invoke(loadout);
			RunSetupRecord runSetupRecord = new RunSetupRecord
			{
				Class = ((object)Unsafe.As<Class, Class>(ref StaticGameData.chosenClass)/*cast due to .constrained prefix*/).ToString(),
				CruciballLevel = (((Object)(object)val != (Object)null) ? val.currentCruciballLevel : 0),
				CustomSeed = loadout.seedInputPopup.hasCustomSeed,
				Seed = (loadout.seedInputPopup.hasCustomSeed ? StaticGameData.currentSeed : ""),
				CustomLoadout = loadout.hasCustomLoadout
			};
			if (runSetupRecord.CustomLoadout)
			{
				runSetupRecord.Orbs = loadout.StartingOrbs.Select((GameObject orb) => ((Object)orb).name).ToList();
				runSetupRecord.Relics = loadout.StartingRelics.Select((Relic relic) => ((object)Unsafe.As<RelicEffect, RelicEffect>(ref relic.effect)/*cast due to .constrained prefix*/).ToString()).ToList();
			}
			Pending = runSetupRecord;
		}

		internal static void RunStarted()
		{
			if (Pending == null)
			{
				return;
			}
			Pending.RunSeed = StaticGameData.currentSeed;
			_current = Pending;
			Pending = null;
			try
			{
				File.WriteAllText(SavePath, _current.Serialize());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't save the run setup to " + SavePath + ": " + ex.Message));
			}
		}

		internal static RunSetupRecord ForCurrentRun()
		{
			string currentSeed = StaticGameData.currentSeed;
			if (string.IsNullOrEmpty(currentSeed))
			{
				return null;
			}
			if (_current != null && _current.IsForRun(currentSeed))
			{
				return _current;
			}
			RunSetupRecord runSetupRecord = Load();
			if (runSetupRecord != null && runSetupRecord.IsForRun(currentSeed))
			{
				_current = runSetupRecord;
				return runSetupRecord;
			}
			if (StaticGameData.CurrentRunStats != null && !StaticGameData.CurrentRunStats.isCustomRun)
			{
				CruciballManager val = Resources.FindObjectsOfTypeAll<CruciballManager>().FirstOrDefault();
				return new RunSetupRecord
				{
					Class = ((object)Unsafe.As<Class, Class>(ref StaticGameData.chosenClass)/*cast due to .constrained prefix*/).ToString(),
					CruciballLevel = (((Object)(object)val != (Object)null) ? val.currentCruciballLevel : 0),
					RunSeed = currentSeed
				};
			}
			return null;
		}

		private static RunSetupRecord Load()
		{
			try
			{
				return File.Exists(SavePath) ? RunSetupRecord.Parse(File.ReadAllText(SavePath)) : null;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read the run setup from " + SavePath + ": " + ex.Message));
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(PlayButton), "ConfirmRunConfigAndStartGame")]
	internal static class RecordSetupOnPlayPatch
	{
		private static void Prefix()
		{
			LoadoutManager val = Object.FindObjectOfType<LoadoutManager>();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Couldn't find the loadout screen when the run started, so this run can't be restarted with the same setup.");
				RunSetup.Pending = null;
			}
			else
			{
				RunSetup.RecordPlay(val);
			}
		}
	}
	[HarmonyPatch(typeof(GameInit), "Start")]
	internal static class RecordSeedOnRunStartPatch
	{
		private static readonly FieldRef<GameInit, LoadMapData> LoadData = AccessTools.FieldRefAccess<GameInit, LoadMapData>("LoadData");

		private static void Postfix(GameInit __instance)
		{
			LoadMapData val = LoadData.Invoke(__instance);
			if ((Object)(object)val != (Object)null && val.NewGame)
			{
				RunSetup.RunStarted();
			}
		}
	}
}
namespace PeglinQuickRestart.Core
{
	public sealed class HoldTimer
	{
		private bool _fired;

		public float HoldSeconds { get; }

		public float Held { get; private set; }

		public float Progress
		{
			get
			{
				if (!_fired)
				{
					if (!(HoldSeconds <= 0f))
					{
						return Math.Min(1f, Held / HoldSeconds);
					}
					return 0f;
				}
				return 1f;
			}
		}

		public bool Charging
		{
			get
			{
				if (Held > 0f)
				{
					return !_fired;
				}
				return false;
			}
		}

		public HoldTimer(float holdSeconds)
		{
			HoldSeconds = Math.Max(0f, holdSeconds);
		}

		public bool Update(bool keyHeld, float deltaTime)
		{
			if (!keyHeld)
			{
				Held = 0f;
				_fired = false;
				return false;
			}
			if (_fired)
			{
				return false;
			}
			Held += Math.Max(0f, deltaTime);
			if (Held >= HoldSeconds)
			{
				_fired = true;
				return true;
			}
			return false;
		}
	}
	public sealed class RunSetupRecord
	{
		public string Class = "";

		public int CruciballLevel;

		public bool CustomSeed;

		public string Seed = "";

		public bool CustomLoadout;

		public List<string> Orbs = new List<string>();

		public List<string> Relics = new List<string>();

		public string RunSeed = "";

		public bool IsForRun(string currentSeed)
		{
			if (!string.IsNullOrEmpty(RunSeed))
			{
				return RunSeed == currentSeed;
			}
			return false;
		}

		public string Serialize()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Class=").Append(Class).Append('\n');
			stringBuilder.Append("CruciballLevel=").Append(CruciballLevel).Append('\n');
			stringBuilder.Append("CustomSeed=").Append(CustomSeed).Append('\n');
			stringBuilder.Append("Seed=").Append(Seed).Append('\n');
			stringBuilder.Append("CustomLoadout=").Append(CustomLoadout).Append('\n');
			stringBuilder.Append("Orbs=").Append(string.Join(",", Orbs)).Append('\n');
			stringBuilder.Append("Relics=").Append(string.Join(",", Relics)).Append('\n');
			stringBuilder.Append("RunSeed=").Append(RunSeed).Append('\n');
			return stringBuilder.ToString();
		}

		public static RunSetupRecord Parse(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string[] array = text.Split(new char[1] { '\n' });
			foreach (string text2 in array)
			{
				int num = text2.IndexOf('=');
				if (num > 0)
				{
					dictionary[text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim();
				}
			}
			if (!dictionary.TryGetValue("Class", out var value) || value.Length == 0 || !dictionary.TryGetValue("CruciballLevel", out var value2) || !int.TryParse(value2, out var result) || !dictionary.TryGetValue("CustomSeed", out var value3) || !bool.TryParse(value3, out var result2) || !dictionary.TryGetValue("CustomLoadout", out var value4) || !bool.TryParse(value4, out var result3) || !dictionary.TryGetValue("RunSeed", out var value5) || value5.Length == 0)
			{
				return null;
			}
			dictionary.TryGetValue("Seed", out var value6);
			if (result2 && string.IsNullOrEmpty(value6))
			{
				return null;
			}
			dictionary.TryGetValue("Orbs", out var value7);
			dictionary.TryGetValue("Relics", out var value8);
			return new RunSetupRecord
			{
				Class = value,
				CruciballLevel = result,
				CustomSeed = result2,
				Seed = (result2 ? value6 : ""),
				CustomLoadout = result3,
				Orbs = SplitList(value7),
				Relics = SplitList(value8),
				RunSeed = value5
			};
		}

		private static List<string> SplitList(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return new List<string>();
			}
			return (from item in value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select item.Trim()).ToList();
		}
	}
}