Decompiled source of ContinueGame v1.0.2

BepInEx/plugins/ContinueGame/ContinueGame.dll

Decompiled a week ago
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("ContinueGame")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+7a0536a753a423517acb829c94b61c6565ec97b7")]
[assembly: AssemblyProduct("ContinueGame")]
[assembly: AssemblyTitle("ContinueGame")]
[assembly: AssemblyVersion("1.0.2.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 ContinueGame
{
	[BepInPlugin("Slikfoul.ContinueGame", "ContinueGame", "1.0.2")]
	public sealed class ContinueGamePlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(FejdStartup), "Start")]
		private static class MenuPatch
		{
			private static void Postfix(FejdStartup __instance)
			{
				Instance?.CreateButton(__instance);
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "JoinServer")]
		private static class JoinPatch
		{
			private static void Prefix(FejdStartup __instance)
			{
				Instance?.CaptureJoin(__instance);
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "OnStartGame")]
		private static class OrdinaryJoinPatch
		{
			private static void Prefix()
			{
				Instance?.CancelPending();
			}
		}

		[HarmonyPatch(typeof(ZNet), "SendPeerInfo")]
		private static class PasswordPatch
		{
			private static void Prefix(ZNet __instance, string password)
			{
				Instance?.CapturePassword(__instance, password);
			}

			private static void Postfix(ZNet __instance)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				if (!__instance.IsServer() && (int)ZNet.GetConnectionStatus() == 1)
				{
					Instance?._loadingScreen?.Advance(LoadingStage.Authenticating);
				}
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "TransitionToMainScene")]
		private static class LoadingStartPatch
		{
			private static void Prefix(FejdStartup __instance)
			{
				Instance?.BeginLoading(__instance);
			}
		}

		[HarmonyPatch(typeof(FejdStartup), "LoadMainScene")]
		private static class WorldLoadingPatch
		{
			private static void Prefix()
			{
				Instance?._loadingScreen?.Advance(LoadingStage.LoadingScene);
			}
		}

		[HarmonyPatch(typeof(ZNet), "ClientConnect")]
		private static class ConnectingPatch
		{
			private static void Prefix()
			{
				Instance?._loadingScreen?.Advance(LoadingStage.Connecting);
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")]
		private static class HandshakePatch
		{
			private static void Prefix(ZNet __instance, bool needPassword)
			{
				if (!__instance.IsServer())
				{
					Instance?._loadingScreen?.Advance(needPassword ? LoadingStage.SendingPassword : LoadingStage.Authenticating);
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		private static class WorldInfoPatch
		{
			private static void Prefix(ZNet __instance)
			{
				if (!__instance.IsServer())
				{
					Instance?._loadingScreen?.Advance(LoadingStage.ReceivingWorld);
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
		private static class NativeLoadingPatch
		{
			private static void Postfix(Hud __instance)
			{
				Instance?.UpdateNativeLoading(__instance);
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static PopupButtonCallback <>9__33_0;

			internal void <Warning>b__33_0()
			{
				UnifiedPopup.Pop();
			}
		}

		public const string PluginId = "Slikfoul.ContinueGame";

		internal static ContinueGamePlugin Instance;

		private static readonly FieldInfo PasswordField = AccessTools.Field(typeof(FejdStartup), "<ServerPassword>k__BackingField");

		private Harmony _harmony;

		private PrivateSessionStorage _storage;

		private SessionRecord _saved;

		private SessionRecord _pending;

		private string _pendingPassword;

		private bool _passwordInjected;

		private string _previousPassword;

		private Button _button;

		private FejdStartup _menu;

		private bool _busy;

		private bool _loadingScheduled;

		private string _label;

		private TMP_Text[] _tmpLabels;

		private Text[] _textLabels;

		private CrossPlatformPasswordProtection _passwordProtection;

		private ContinueLoadingScreen _loadingScreen;

		private bool Russian
		{
			get
			{
				if (Localization.instance != null)
				{
					return Localization.instance.GetSelectedLanguage() == "Russian";
				}
				return false;
			}
		}

		private string Text(string ru, string en)
		{
			if (!Russian)
			{
				return en;
			}
			return ru;
		}

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Instance = this;
			if (PasswordField == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Required Valheim password integration is unavailable.");
				return;
			}
			_harmony = new Harmony("Slikfoul.ContinueGame");
			_harmony.PatchAll(typeof(ContinueGamePlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ContinueGame loaded.");
		}

		private void InitializeStorage()
		{
			_saved = null;
			_storage = null;
			_passwordProtection = null;
			try
			{
				string saveDataPath = Utils.GetSaveDataPath((FileSource)2);
				if (string.IsNullOrWhiteSpace(saveDataPath))
				{
					throw new IOException("Local save directory is unavailable.");
				}
				_storage = new PrivateSessionStorage(Paths.ConfigPath, Path.GetFullPath(saveDataPath));
				_passwordProtection = _storage.PasswordProtection;
				_saved = _storage.Load();
			}
			catch (Exception)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Saved session could not be read. Join normally to save a new session.");
			}
		}

		private void OnDestroy()
		{
			CancelPending();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal void CancelPending()
		{
			_loadingScreen?.Dispose();
			_loadingScreen = null;
			RestorePassword();
			_pending = null;
			_pendingPassword = null;
			_busy = false;
			_loadingScheduled = false;
		}

		private void RestorePassword()
		{
			if (_passwordInjected)
			{
				PasswordField.SetValue(null, _previousPassword);
				_previousPassword = null;
				_passwordInjected = false;
			}
		}

		private void Update()
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Invalid comparison between Unknown and I4
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Invalid comparison between Unknown and I4
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Invalid comparison between Unknown and I4
			if (_loadingScreen != null)
			{
				try
				{
					_loadingScreen.Tick();
					if (_loadingScreen.IsFinished)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)"Native loading artwork is ready; Continue preloading panel hidden.");
						_loadingScreen = null;
					}
				}
				catch (Exception)
				{
					_loadingScreen.Dispose();
					_loadingScreen = null;
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Loading visuals could not be updated; connection will continue normally.");
				}
			}
			if ((Object)(object)_button != (Object)null)
			{
				string text = Text("Продолжить", "Continue");
				if (text != _label)
				{
					TMP_Text[] tmpLabels = _tmpLabels;
					for (int i = 0; i < tmpLabels.Length; i++)
					{
						tmpLabels[i].text = text;
					}
					Text[] textLabels = _textLabels;
					for (int i = 0; i < textLabels.Length; i++)
					{
						textLabels[i].text = text;
					}
					_label = text;
				}
				((Selectable)_button).interactable = _saved != null && !_busy;
			}
			if (_pending != null && (Object)(object)_menu != (Object)null)
			{
				if (((MonoBehaviour)_menu).IsInvoking("LoadMainSceneIfBackendSelected"))
				{
					_loadingScheduled = true;
				}
				else if (_loadingScheduled && !_menu.m_loading.activeSelf)
				{
					CancelPending();
				}
			}
			if (_pending == null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				return;
			}
			ConnectionStatus connectionStatus = ZNet.GetConnectionStatus();
			if ((int)connectionStatus > 2)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Connection did not succeed; keeping the last successful session.");
				CancelPending();
				return;
			}
			if ((int)connectionStatus == 2)
			{
				_loadingScreen?.Advance(LoadingStage.LoadingArea);
			}
			if ((int)connectionStatus != 2 || (Object)(object)Game.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
				if (playerProfile != null)
				{
					_pending.CharacterFilename = playerProfile.GetFilename();
					_pending.CharacterId = playerProfile.GetPlayerID();
					_storage.Save(_pending, _pendingPassword ?? "");
					_saved = _pending;
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Last successful server and character saved; password protected.");
				}
			}
			catch (Exception)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"The successful session could not be saved. The previous session was kept.");
			}
			finally
			{
				CancelPending();
			}
		}

		internal void CaptureJoin(FejdStartup startup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ServerJoinData serverToJoin = startup.GetServerToJoin();
				if (((ServerJoinData)(ref serverToJoin)).IsValid)
				{
					_pending = RecordServer(serverToJoin);
					if (!_passwordInjected)
					{
						_pendingPassword = null;
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Tracking a server connection attempt.");
				}
			}
			catch (Exception)
			{
				CancelPending();
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not track the connection; ordinary joining remains available.");
			}
		}

		internal void CapturePassword(ZNet network, string password)
		{
			if (_pending != null && !network.IsServer())
			{
				_pendingPassword = password ?? "";
				RestorePassword();
			}
		}

		private unsafe static SessionRecord RecordServer(ServerJoinData server)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected I4, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			SessionRecord sessionRecord = new SessionRecord
			{
				ServerOwner = (((PlatformUserID)(ref server.m_owner)).IsValid ? ((object)(*(PlatformUserID*)(&server.m_owner))/*cast due to .constrained prefix*/).ToString() : null)
			};
			ServerJoinDataType type = server.m_type;
			switch (type - 1)
			{
			case 2:
			{
				sessionRecord.ServerKind = "Dedicated";
				ServerJoinDataDedicated dedicated = ((ServerJoinData)(ref server)).Dedicated;
				sessionRecord.Address = ((ServerJoinDataDedicated)(ref dedicated)).m_host;
				sessionRecord.Port = ((ServerJoinData)(ref server)).Dedicated.m_port;
				break;
			}
			case 0:
			{
				sessionRecord.ServerKind = "Steam";
				ulong steamID = ((ServerJoinData)(ref server)).SteamUser.m_joinUserID.m_SteamID;
				sessionRecord.Address = steamID.ToString(CultureInfo.InvariantCulture);
				break;
			}
			case 1:
				sessionRecord.ServerKind = "PlayFab";
				sessionRecord.Address = ((ServerJoinData)(ref server)).PlayFabUser.m_remotePlayerId;
				break;
			default:
				throw new InvalidOperationException("Unsupported server type.");
			}
			return sessionRecord;
		}

		private static ServerJoinData RestoreServer(SessionRecord record)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			ServerJoinData result = default(ServerJoinData);
			switch (record.ServerKind)
			{
			case "Dedicated":
				((ServerJoinData)(ref result))..ctor(new ServerJoinDataDedicated(record.Address, (ushort)record.Port));
				break;
			case "Steam":
				((ServerJoinData)(ref result))..ctor(new ServerJoinDataSteamUser(ulong.Parse(record.Address, CultureInfo.InvariantCulture)));
				break;
			case "PlayFab":
				((ServerJoinData)(ref result))..ctor(new ServerJoinDataPlayFabUser(record.Address));
				break;
			default:
				throw new InvalidDataException("Unsupported server type.");
			}
			PlatformUserID owner = default(PlatformUserID);
			if (PlatformUserID.TryParse(record.ServerOwner, ref owner))
			{
				result.m_owner = owner;
			}
			return result;
		}

		private void Continue()
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			if (_saved == null || (Object)(object)_menu == (Object)null || _busy)
			{
				return;
			}
			try
			{
				_busy = true;
				BeginLoading(_menu);
				PlayerProfile val = null;
				foreach (PlayerProfile allPlayerProfile in SaveSystem.GetAllPlayerProfiles())
				{
					if (allPlayerProfile.GetFilename() == _saved.CharacterFilename && allPlayerProfile.GetPlayerID() == _saved.CharacterId)
					{
						val = allPlayerProfile;
						break;
					}
				}
				if (val == null)
				{
					CancelPending();
					Warning(Text("Сохранённый персонаж не найден. Войдите обычным способом, чтобы сохранить новый вход.", "The saved character was not found. Join normally to save a new session."));
					return;
				}
				AccessTools.Method(typeof(FejdStartup), "SelectCharacter", (Type[])null, (Type[])null).Invoke(_menu, new object[2]
				{
					val.GetFilename(),
					val.m_fileSource
				});
				_loadingScreen?.Advance(LoadingStage.RestoringPassword);
				string text;
				try
				{
					text = _passwordProtection.Unprotect(_saved.ProtectedPassword);
				}
				catch (Exception)
				{
					CancelPending();
					Warning(Text("Не удалось прочитать сохранённый пароль. Войдите обычным способом и введите пароль снова.", "The saved password could not be read. Join normally and enter your password again."));
					return;
				}
				_previousPassword = (string)PasswordField.GetValue(null);
				_passwordInjected = true;
				PasswordField.SetValue(null, (text.Length == 0) ? null : text);
				_pendingPassword = text;
				_loadingScreen?.Advance(LoadingStage.FindingServer);
				_menu.SetServerToJoin(RestoreServer(_saved));
				_menu.JoinServer();
				if (!((MonoBehaviour)_menu).IsInvoking("LoadMainSceneIfBackendSelected") && !ZNet.HasServerHost() && (_saved.ServerKind != "PlayFab" || PlayFabManager.IsLoggedIn))
				{
					CancelPending();
				}
			}
			catch (Exception)
			{
				CancelPending();
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Continue could not start. Ordinary joining remains available.");
				Warning(Text("Не удалось начать подключение. Войдите на сервер обычным способом.", "The connection could not be started. Join the server normally."));
			}
		}

		private void Warning(string message)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			string text = Text("Продолжить", "Continue");
			object obj = <>c.<>9__33_0;
			if (obj == null)
			{
				PopupButtonCallback val = delegate
				{
					UnifiedPopup.Pop();
				};
				<>c.<>9__33_0 = val;
				obj = (object)val;
			}
			UnifiedPopup.Push((PopupBase)new WarningPopup(text, message, (PopupButtonCallback)obj, false));
		}

		internal void BeginLoading(FejdStartup startup)
		{
			if (!_busy || _loadingScreen != null)
			{
				return;
			}
			try
			{
				_loadingScreen = new ContinueLoadingScreen(startup);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Continue loading screen shown.");
			}
			catch (Exception)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Loading visuals could not be created; connection will continue normally.");
			}
		}

		internal void UpdateNativeLoading(Hud hud)
		{
			if (_loadingScreen == null)
			{
				return;
			}
			try
			{
				_loadingScreen.HandOffToNative(hud);
			}
			catch (Exception)
			{
				_loadingScreen.Dispose();
				_loadingScreen = null;
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Preloading UI could not be hidden; connection will continue normally.");
			}
		}

		internal void CreateButton(FejdStartup startup)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			CancelPending();
			InitializeStorage();
			_menu = startup;
			try
			{
				if ((Object)(object)startup.m_menuList.transform.Find("ContinueGameButton") != (Object)null)
				{
					return;
				}
				Button[] componentsInChildren = startup.m_menuList.GetComponentsInChildren<Button>(true);
				Button val = null;
				Button[] array = componentsInChildren;
				foreach (Button val2 in array)
				{
					if (((Object)val2).name == "StartGame" || ((Object)val2).name == "Start")
					{
						val = val2;
						break;
					}
				}
				if ((Object)(object)val == (Object)null && componentsInChildren.Length != 0)
				{
					val = componentsInChildren[0];
				}
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("Main menu button not found.");
				}
				_button = Object.Instantiate<Button>(val, ((Component)val).transform.parent);
				((Object)_button).name = "ContinueGameButton";
				_button.onClick = new ButtonClickedEvent();
				((UnityEvent)_button.onClick).AddListener(new UnityAction(Continue));
				_tmpLabels = ((Component)_button).GetComponentsInChildren<TMP_Text>(true);
				_textLabels = ((Component)_button).GetComponentsInChildren<Text>(true);
				_label = null;
				((Component)_button).transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex());
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				RectTransform component2 = ((Component)_button).GetComponent<RectTransform>();
				if ((Object)(object)((Component)((Component)val).transform.parent).GetComponent<LayoutGroup>() == (Object)null)
				{
					Rect rect = component.rect;
					float num = ((Rect)(ref rect)).height + 8f;
					float num2 = float.MaxValue;
					array = componentsInChildren;
					foreach (Button val3 in array)
					{
						if (!((Object)(object)((Component)val3).transform.parent != (Object)(object)((Component)val).transform.parent))
						{
							float num3 = Mathf.Abs(((Component)val3).GetComponent<RectTransform>().anchoredPosition.y - component.anchoredPosition.y);
							if (num3 > 1f)
							{
								num2 = Mathf.Min(num2, num3);
							}
						}
					}
					if (num2 != float.MaxValue)
					{
						num = num2;
					}
					component2.anchoredPosition = component.anchoredPosition + new Vector2(0f, num);
				}
				((Component)_button).gameObject.SetActive(true);
				((Selectable)_button).interactable = _saved != null;
				AccessTools.Field(typeof(FejdStartup), "m_menuButtons").SetValue(startup, (_saved != null) ? startup.m_menuList.GetComponentsInChildren<Button>() : componentsInChildren);
				Navigation navigation = ((Selectable)_button).navigation;
				((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)val;
				((Selectable)_button).navigation = navigation;
				if (_saved != null)
				{
					navigation = ((Selectable)val).navigation;
					((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)_button;
					((Selectable)val).navigation = navigation;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Continue button added to the main menu.");
			}
			catch (Exception)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Continue button could not be added; ordinary joining remains available.");
			}
		}
	}
	internal sealed class ContinueLoadingScreen : IDisposable
	{
		private static readonly Color Gold = new Color(0.92f, 0.76f, 0.44f, 1f);

		private static readonly string[] RussianStages = new string[9] { "Выбор персонажа", "Восстановление пароля", "Поиск сервера", "Загрузка игровой сцены", "Подключение к серверу", "Передача пароля", "Проверка входа", "Получение данных мира", "Загрузка области мира" };

		private static readonly string[] EnglishStages = new string[9] { "Selecting character", "Restoring password", "Finding server", "Loading game scene", "Connecting to server", "Sending password", "Authenticating", "Receiving world data", "Loading world area" };

		private readonly LoadingState _state = new LoadingState();

		private readonly GameObject _root;

		private readonly CanvasGroup _visibility;

		private readonly TMP_Text _stageText;

		private readonly RectTransform _shine;

		private readonly Texture2D _shineTexture;

		private readonly Sprite _shineSprite;

		private readonly float _startedAt;

		public bool IsFinished { get; private set; }

		private static bool Russian
		{
			get
			{
				if (Localization.instance != null)
				{
					return Localization.instance.GetSelectedLanguage() == "Russian";
				}
				return false;
			}
		}

		public ContinueLoadingScreen(FejdStartup startup)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			_root = new GameObject("ContinueGamePreloading", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(CanvasGroup)
			});
			try
			{
				Object.DontDestroyOnLoad((Object)(object)_root);
				Canvas component = _root.GetComponent<Canvas>();
				component.renderMode = (RenderMode)0;
				component.sortingOrder = 32000;
				CanvasScaler component2 = _root.GetComponent<CanvasScaler>();
				component2.uiScaleMode = (ScaleMode)1;
				component2.referenceResolution = new Vector2(1920f, 1080f);
				component2.matchWidthOrHeight = 0.5f;
				_visibility = _root.GetComponent<CanvasGroup>();
				_visibility.interactable = false;
				_visibility.blocksRaycasts = false;
				_startedAt = Time.unscaledTime;
				Image obj = Add<Image>("Backdrop", (Transform)null);
				Stretch(((Graphic)obj).rectTransform);
				((Graphic)obj).color = new Color(0.025f, 0.022f, 0.016f, 1f);
				((Graphic)obj).raycastTarget = false;
				TMP_Text componentInChildren = startup.m_menuList.GetComponentInChildren<TMP_Text>(true);
				TMP_Text obj2 = Label("Title", componentInChildren, 40f);
				obj2.text = "Loading";
				Place(obj2.rectTransform, new Vector2(0.5f, 0.55f), new Vector2(1000f, 80f));
				_stageText = Label("CurrentStage", componentInChildren, 30f);
				Place(_stageText.rectTransform, new Vector2(0.5f, 0.45f), new Vector2(1100f, 80f));
				Image obj3 = Add<Image>("BarBorder", (Transform)null);
				Place(((Graphic)obj3).rectTransform, new Vector2(0.5f, 0.39f), new Vector2(564f, 12f));
				((Graphic)obj3).color = new Color(Gold.r, Gold.g, Gold.b, 0.32f);
				((Graphic)obj3).raycastTarget = false;
				Image val = Add<Image>("BarTrack", (Transform)null);
				Place(((Graphic)val).rectTransform, new Vector2(0.5f, 0.39f), new Vector2(560f, 8f));
				((Graphic)val).color = new Color(0.1f, 0.08f, 0.04f, 1f);
				((Graphic)val).raycastTarget = false;
				((Component)val).gameObject.AddComponent<RectMask2D>();
				_shineTexture = new Texture2D(96, 1, (TextureFormat)4, false);
				((Texture)_shineTexture).wrapMode = (TextureWrapMode)1;
				for (int i = 0; i < 96; i++)
				{
					float num = Mathf.Sin((float)Math.PI * (float)i / 95f);
					_shineTexture.SetPixel(i, 0, new Color(Gold.r, Gold.g, Gold.b, num * num));
				}
				_shineTexture.Apply(false, true);
				_shineSprite = Sprite.Create(_shineTexture, new Rect(0f, 0f, 96f, 1f), new Vector2(0.5f, 0.5f));
				Image val2 = Add<Image>("BarGlow", ((Component)val).transform);
				val2.sprite = _shineSprite;
				((Graphic)val2).raycastTarget = false;
				_shine = ((Graphic)val2).rectTransform;
				Place(_shine, new Vector2(0f, 0.5f), new Vector2(190f, 8f));
				Tick();
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		public void Advance(LoadingStage stage)
		{
			_state.Advance(stage);
		}

		public void HandOffToNative(Hud hud)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!IsFinished && !((Object)(object)hud == (Object)null) && !((Object)(object)hud.m_loadingScreen == (Object)null))
			{
				Image loadingImage = hud.m_loadingImage;
				bool artworkVisible = (Object)(object)loadingImage != (Object)null && ((Behaviour)loadingImage).isActiveAndEnabled && (Object)(object)loadingImage.sprite != (Object)null && ((Graphic)loadingImage).color.a > 0f && (Object)(object)((Graphic)loadingImage).canvas != (Object)null && ((Behaviour)((Graphic)loadingImage).canvas).isActiveAndEnabled && ((Graphic)loadingImage).canvasRenderer.GetInheritedAlpha() > 0f;
				bool worldLoadingActive = (Object)(object)hud.m_loadingProgress != (Object)null && hud.m_loadingProgress.activeInHierarchy;
				_state.ObserveNativeLoading(((Component)hud.m_loadingScreen).gameObject.activeInHierarchy, hud.m_loadingScreen.alpha, worldLoadingActive, artworkVisible);
				if (_state.Completed)
				{
					Dispose();
				}
			}
		}

		public void Tick()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			if (IsFinished)
			{
				return;
			}
			HandOffToNative(Hud.instance);
			if (!IsFinished)
			{
				string text = (Russian ? RussianStages : EnglishStages)[(int)_state.Stage];
				if (_stageText.text != text)
				{
					_stageText.text = text;
				}
				float num = Mathf.Repeat((Time.unscaledTime - _startedAt + 0.9f) / 2.6f, 1f);
				_shine.anchoredPosition = new Vector2(Mathf.Lerp(-95f, 655f, Mathf.SmoothStep(0f, 1f, num)), 0f);
				_visibility.alpha = ((UnifiedPopup.IsVisible() || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.InPasswordDialog())) ? 0f : 1f);
			}
		}

		private TMP_Text Label(string name, TMP_Text template, float size)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = Add<TextMeshProUGUI>(name, (Transform)null);
			if ((Object)(object)template != (Object)null)
			{
				((TMP_Text)val).font = template.font;
				((TMP_Text)val).fontSharedMaterial = template.fontSharedMaterial;
			}
			((TMP_Text)val).fontSize = size;
			((Graphic)val).color = Gold;
			((TMP_Text)val).alignment = (TextAlignmentOptions)514;
			((Graphic)val).raycastTarget = false;
			return (TMP_Text)(object)val;
		}

		private T Add<T>(string name, Transform parent = null) where T : Component
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Object)(object)parent != (Object)null) ? parent : _root.transform, false);
			return val.AddComponent<T>();
		}

		private static void Stretch(RectTransform rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			Vector2 offsetMin = (rect.offsetMax = Vector2.zero);
			rect.offsetMin = offsetMin;
		}

		private static void Place(RectTransform rect, Vector2 anchor, Vector2 size)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Vector2 anchorMin = (rect.anchorMax = anchor);
			rect.anchorMin = anchorMin;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.sizeDelta = size;
			rect.anchoredPosition = Vector2.zero;
		}

		public void Dispose()
		{
			if (!IsFinished)
			{
				IsFinished = true;
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
					Object.Destroy((Object)(object)_root);
				}
				if ((Object)(object)_shineSprite != (Object)null)
				{
					Object.Destroy((Object)(object)_shineSprite);
				}
				if ((Object)(object)_shineTexture != (Object)null)
				{
					Object.Destroy((Object)(object)_shineTexture);
				}
			}
		}
	}
	public enum LoadingStage
	{
		SelectingCharacter,
		RestoringPassword,
		FindingServer,
		LoadingScene,
		Connecting,
		SendingPassword,
		Authenticating,
		ReceivingWorld,
		LoadingArea
	}
	public sealed class LoadingState
	{
		public LoadingStage Stage { get; private set; }

		public bool Completed { get; private set; }

		public void Advance(LoadingStage stage)
		{
			if (!Completed && stage > Stage)
			{
				Stage = stage;
			}
		}

		public void ObserveNativeLoading(bool active, float alpha, bool worldLoadingActive, bool artworkVisible)
		{
			if (active && alpha > 0f && worldLoadingActive && artworkVisible)
			{
				Completed = true;
			}
		}
	}
	public static class PasswordProtection
	{
		private struct DataBlob
		{
			public int Length;

			public IntPtr Data;
		}

		[DllImport("crypt32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool CryptProtectData(ref DataBlob input, string description, IntPtr entropy, IntPtr reserved, IntPtr prompt, int flags, out DataBlob output);

		[DllImport("crypt32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool CryptUnprotectData(ref DataBlob input, IntPtr description, IntPtr entropy, IntPtr reserved, IntPtr prompt, int flags, out DataBlob output);

		[DllImport("kernel32.dll")]
		private static extern IntPtr LocalFree(IntPtr memory);

		public static string Protect(string password)
		{
			if (string.IsNullOrEmpty(password))
			{
				return "";
			}
			return Convert.ToBase64String(Transform(Encoding.UTF8.GetBytes(password), protect: true));
		}

		public static string Unprotect(string protectedPassword)
		{
			if (string.IsNullOrEmpty(protectedPassword))
			{
				return "";
			}
			byte[] array = Transform(Convert.FromBase64String(protectedPassword), protect: false);
			try
			{
				return Encoding.UTF8.GetString(array);
			}
			finally
			{
				Array.Clear(array, 0, array.Length);
			}
		}

		private static byte[] Transform(byte[] bytes, bool protect)
		{
			if (Environment.OSVersion.Platform != PlatformID.Win32NT)
			{
				throw new PlatformNotSupportedException("Password protection requires Windows.");
			}
			DataBlob input = new DataBlob
			{
				Length = bytes.Length,
				Data = Marshal.AllocHGlobal(bytes.Length)
			};
			DataBlob output = default(DataBlob);
			try
			{
				Marshal.Copy(bytes, 0, input.Data, bytes.Length);
				if (!(protect ? CryptProtectData(ref input, "ContinueGame", IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, out output) : CryptUnprotectData(ref input, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, out output)))
				{
					throw new Win32Exception(Marshal.GetLastWin32Error());
				}
				byte[] array = new byte[output.Length];
				Marshal.Copy(output.Data, array, 0, array.Length);
				return array;
			}
			finally
			{
				for (int i = 0; i < input.Length; i++)
				{
					Marshal.WriteByte(input.Data, i, 0);
				}
				Marshal.FreeHGlobal(input.Data);
				if (output.Data != IntPtr.Zero)
				{
					if (!protect)
					{
						for (int j = 0; j < output.Length; j++)
						{
							Marshal.WriteByte(output.Data, j, 0);
						}
					}
					LocalFree(output.Data);
				}
				Array.Clear(bytes, 0, bytes.Length);
			}
		}
	}
	public sealed class CrossPlatformPasswordProtection
	{
		private readonly PortablePasswordProtection _portable;

		public CrossPlatformPasswordProtection(string keyDirectory)
		{
			_portable = new PortablePasswordProtection(keyDirectory);
		}

		public string Protect(string password)
		{
			if (Environment.OSVersion.Platform != PlatformID.Win32NT)
			{
				return _portable.Protect(password);
			}
			return PasswordProtection.Protect(password);
		}

		public string Unprotect(string password)
		{
			if (password == null || !password.StartsWith("portable-v1:", StringComparison.Ordinal))
			{
				return PasswordProtection.Unprotect(password);
			}
			return _portable.Unprotect(password);
		}
	}
	public sealed class PortablePasswordProtection
	{
		public const string Prefix = "portable-v1:";

		private readonly string _directory;

		private readonly string _keyPath;

		public PortablePasswordProtection(string directory)
		{
			_directory = Path.GetFullPath(directory);
			_keyPath = Path.Combine(_directory, "password.key");
		}

		private byte[] ReadKey(bool create)
		{
			if (!Directory.Exists(_directory))
			{
				if (!create)
				{
					throw new FileNotFoundException("Password key is missing.");
				}
				Directory.CreateDirectory(_directory);
			}
			if (!File.Exists(_keyPath) && create)
			{
				byte[] array = new byte[64];
				using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create())
				{
					randomNumberGenerator.GetBytes(array);
				}
				bool flag = false;
				try
				{
					using FileStream fileStream = new FileStream(_keyPath, FileMode.CreateNew, FileAccess.Write, FileShare.None);
					flag = true;
					fileStream.Write(array, 0, array.Length);
					fileStream.Flush(flushToDisk: true);
				}
				catch
				{
					if (flag)
					{
						try
						{
							File.Delete(_keyPath);
						}
						catch (IOException)
						{
						}
					}
					throw;
				}
				finally
				{
					Array.Clear(array, 0, array.Length);
				}
			}
			if (!File.Exists(_keyPath))
			{
				throw new FileNotFoundException("Password key is missing.");
			}
			if (new FileInfo(_keyPath).Length != 64)
			{
				throw new CryptographicException("Invalid password key.");
			}
			return File.ReadAllBytes(_keyPath);
		}

		public string Protect(string password)
		{
			if (string.IsNullOrEmpty(password))
			{
				return "";
			}
			byte[] array = ReadKey(create: true);
			byte[] bytes = Encoding.UTF8.GetBytes(password);
			byte[] array2 = new byte[32];
			byte[] array3 = new byte[32];
			Buffer.BlockCopy(array, 0, array2, 0, 32);
			Buffer.BlockCopy(array, 32, array3, 0, 32);
			try
			{
				using Aes aes = Aes.Create();
				aes.Key = array2;
				aes.Mode = CipherMode.CBC;
				aes.Padding = PaddingMode.PKCS7;
				aes.GenerateIV();
				byte[] array4;
				using (ICryptoTransform cryptoTransform = aes.CreateEncryptor())
				{
					array4 = cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length);
				}
				byte[] array5 = new byte[17 + array4.Length + 32];
				array5[0] = 1;
				Buffer.BlockCopy(aes.IV, 0, array5, 1, 16);
				Buffer.BlockCopy(array4, 0, array5, 17, array4.Length);
				using (HMACSHA256 hMACSHA = new HMACSHA256(array3))
				{
					Buffer.BlockCopy(hMACSHA.ComputeHash(array5, 0, array5.Length - 32), 0, array5, array5.Length - 32, 32);
				}
				return "portable-v1:" + Convert.ToBase64String(array5);
			}
			finally
			{
				Array.Clear(bytes, 0, bytes.Length);
				Array.Clear(array, 0, array.Length);
				Array.Clear(array2, 0, array2.Length);
				Array.Clear(array3, 0, array3.Length);
			}
		}

		public string Unprotect(string password)
		{
			if (string.IsNullOrEmpty(password))
			{
				return "";
			}
			if (!password.StartsWith("portable-v1:", StringComparison.Ordinal))
			{
				throw new CryptographicException("Unknown password format.");
			}
			byte[] array = Convert.FromBase64String(password.Substring("portable-v1:".Length));
			if (array.Length < 65 || array[0] != 1 || (array.Length - 49) % 16 != 0)
			{
				throw new CryptographicException("Invalid encrypted password.");
			}
			byte[] array2 = ReadKey(create: false);
			byte[] array3 = new byte[32];
			byte[] array4 = new byte[32];
			Buffer.BlockCopy(array2, 0, array3, 0, 32);
			Buffer.BlockCopy(array2, 32, array4, 0, 32);
			try
			{
				using (HMACSHA256 hMACSHA = new HMACSHA256(array4))
				{
					byte[] array5 = hMACSHA.ComputeHash(array, 0, array.Length - 32);
					int num = 0;
					for (int i = 0; i < 32; i++)
					{
						num |= array5[i] ^ array[array.Length - 32 + i];
					}
					if (num != 0)
					{
						throw new CryptographicException("Password authentication failed.");
					}
				}
				using Aes aes = Aes.Create();
				aes.Key = array3;
				aes.Mode = CipherMode.CBC;
				aes.Padding = PaddingMode.PKCS7;
				byte[] array6 = new byte[16];
				Buffer.BlockCopy(array, 1, array6, 0, 16);
				aes.IV = array6;
				byte[] array7;
				using (ICryptoTransform cryptoTransform = aes.CreateDecryptor())
				{
					array7 = cryptoTransform.TransformFinalBlock(array, 17, array.Length - 49);
				}
				try
				{
					return Encoding.UTF8.GetString(array7);
				}
				finally
				{
					Array.Clear(array7, 0, array7.Length);
				}
			}
			finally
			{
				Array.Clear(array2, 0, array2.Length);
				Array.Clear(array3, 0, array3.Length);
				Array.Clear(array4, 0, array4.Length);
			}
		}
	}
	public sealed class PrivateSessionStorage
	{
		private readonly SessionStore _store;

		public readonly CrossPlatformPasswordProtection PasswordProtection;

		public readonly string DirectoryPath;

		public static string ResolveDirectory(string configDirectory, string dataRoot)
		{
			if (string.IsNullOrWhiteSpace(dataRoot) || !Path.IsPathRooted(dataRoot))
			{
				throw new IOException("The local Valheim save directory is unavailable.");
			}
			string text = Path.GetFullPath(configDirectory).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
			string s = ((Environment.OSVersion.Platform == PlatformID.Win32NT) ? text.ToUpperInvariant() : text);
			string path;
			using (SHA256 sHA = SHA256.Create())
			{
				path = BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(s))).Replace("-", "").ToLowerInvariant();
			}
			string fullPath = Path.GetFullPath(Path.Combine(dataRoot, "ContinueGame", path));
			string text2 = Path.GetDirectoryName(Path.GetDirectoryName(text)).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			string value = text2 + directorySeparatorChar;
			StringComparison comparisonType = ((Environment.OSVersion.Platform == PlatformID.Win32NT) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
			if (fullPath.StartsWith(value, comparisonType))
			{
				throw new IOException("Private data must be outside the mod profile.");
			}
			return fullPath;
		}

		public PrivateSessionStorage(string configDirectory, string dataRoot)
		{
			DirectoryPath = ResolveDirectory(configDirectory, dataRoot);
			_store = new SessionStore(Path.Combine(DirectoryPath, "last-session.json"));
			PasswordProtection = new CrossPlatformPasswordProtection(Path.Combine(DirectoryPath, "keys"));
		}

		public SessionRecord Load()
		{
			SessionRecord sessionRecord = _store.Load();
			if (sessionRecord != null)
			{
				PasswordProtection.Unprotect(sessionRecord.ProtectedPassword);
			}
			return sessionRecord;
		}

		public void Save(SessionRecord record, string password)
		{
			if (record == null)
			{
				throw new InvalidDataException("Invalid session.");
			}
			password = password ?? "";
			Directory.CreateDirectory(DirectoryPath);
			record.ProtectedPassword = PasswordProtection.Protect(password);
			_store.Save(record);
			SessionRecord sessionRecord = _store.Load();
			if (sessionRecord == null || sessionRecord.ProtectedPassword != record.ProtectedPassword || PasswordProtection.Unprotect(sessionRecord.ProtectedPassword) != password)
			{
				throw new InvalidDataException("Private session verification failed.");
			}
		}
	}
	[DataContract]
	public sealed class SessionRecord
	{
		[DataMember]
		public int Version = 1;

		[DataMember]
		public string ServerKind;

		[DataMember]
		public string Address;

		[DataMember]
		public int Port;

		[DataMember]
		public string ServerOwner;

		[DataMember]
		public string CharacterFilename;

		[DataMember]
		public long CharacterId;

		[DataMember]
		public string ProtectedPassword;

		public bool IsValid()
		{
			if (Version != 1 || string.IsNullOrWhiteSpace(CharacterFilename) || string.IsNullOrWhiteSpace(Address) || ProtectedPassword == null)
			{
				return false;
			}
			if (ServerKind == "Dedicated")
			{
				if (Port > 0)
				{
					return Port <= 65535;
				}
				return false;
			}
			if (ServerKind == "PlayFab")
			{
				return true;
			}
			if (ServerKind == "Steam" && ulong.TryParse(Address, out var result))
			{
				return result != 0;
			}
			return false;
		}
	}
	public sealed class SessionStore
	{
		private readonly string _path;

		public SessionStore(string path)
		{
			_path = path;
		}

		public SessionRecord Load()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(_path))
			{
				return null;
			}
			if (new FileInfo(_path).Length > 65536)
			{
				throw new InvalidDataException("Saved session is too large.");
			}
			using FileStream fileStream = File.OpenRead(_path);
			SessionRecord sessionRecord = (SessionRecord)((XmlObjectSerializer)new DataContractJsonSerializer(typeof(SessionRecord))).ReadObject((Stream)fileStream);
			if (sessionRecord == null || !sessionRecord.IsValid())
			{
				throw new InvalidDataException("Invalid saved session.");
			}
			return sessionRecord;
		}

		public void Save(SessionRecord record)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (record == null || !record.IsValid())
			{
				throw new InvalidDataException("Invalid session.");
			}
			Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(_path)));
			string text = _path + ".tmp";
			try
			{
				using (FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write, FileShare.None))
				{
					((XmlObjectSerializer)new DataContractJsonSerializer(typeof(SessionRecord))).WriteObject((Stream)fileStream, (object)record);
					fileStream.Flush(flushToDisk: true);
				}
				if (File.Exists(_path))
				{
					File.Replace(text, _path, null);
				}
				else
				{
					File.Move(text, _path);
				}
			}
			finally
			{
				if (File.Exists(text))
				{
					File.Delete(text);
				}
			}
		}
	}
}